简体   繁体   English

Perl就地替换

[英]Perl in-place substitution

In Perl one liner, we can use the -i argument to do an in-place substitution. 在Perl one liner中,我们可以使用-i参数进行就地替换。 What's the equivalence of -i when writing perl code in the IDE? 在IDE中编写perl代码时-i的等价性是什么?

Consider the following code: 请考虑以下代码:

binmode(STDOUT, ':raw');
open my $fh, '<', $filename;
while (<$fh>) {
    s/^/<rootroot>/ if $.==1;
    if (/(<link rel[^<>\n]*?)(\/?)(>)/g) {
        my ($p1, $p2, $p3) = ($1, $2, $3);
        s/$p1$p2$p3/($p2 ? qq|$p1$p2$p3<span class="entry">| : qq|$p1\/$p3<span class="entry">|)/ge;
    };
    s/<\/>/<entry_end><\/entry_end>/;
    s/$/<\/rootroot>/ if eof;

}

How can we save all the lines of changes in-place? 我们如何才能保存所有变更线?

Because I need to do a quick validation on the html file using XML::LibXML right after the in-place change of the html source.. 因为我需要在html源的就地更改后立即使用XML :: LibXML对html文件进行快速验证。

Thanks in advance. 提前致谢。

You can try something like this: 你可以尝试这样的事情:

my $filename = 'test.dat';
@ARGV = ($filename);
$^I = '';
while(<<>>) {
    binmode(ARGV, ':raw');
    # Do the substitiution on $_ here ...
    print;
}

I did not find out how to set binmode before the loop, since ARGV is only defined after the <> operator has been used. 我没有找到如何在循环之前设置binmode ,因为ARGV仅在使用<>运算符之后定义。

  • The $^I and ARGV variables are decribed in perlvar $^IARGV变量在perlvar

  • See perlop for information about why you should use <<>> instead of <> . 有关为什么应该使用<<>>而不是<>信息,请参阅perlop

Some notes: 一些说明:

  • The while(<>) { ... } According to perlop , the loop while(<>) { ... }根据perlop ,循环
 while (<>) { ... # code for each line } 

is equivalent to the following Perl-like pseudo code: 等效于以下类似Perl的伪代码:

 unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } } 
  • Using in-place edit without a backup file: $^I="" : 在没有备份文件的情况下使用就地编辑: $^I=""

According to perlrun : 根据perlrun

If no extension is supplied, and your system supports it, the original file is kept open without a name while the output is redirected to a new file with the original filename. 如果没有提供扩展,并且您的系统支持它,则原始文件将保持打开状态而没有名称,而输出将重定向到具有原始文件名的新文件。 When perl exits, cleanly or not, the original file is unlinked. 当perl退出时,干净利落或不干净,原始文件被取消链接。

and some more information in this blog: 以及博客中的更多信息:

Perl opens and immediately unlink()s the original file, then opens a new file with the same name (new file descriptor and inode), and sends output to this second file; Perl打开并立即取消链接()原始文件,然后打开一个具有相同名称的新文件(新文件描述符和inode),并将输出发送到第二个文件; at the end, the old file is closed and thus deleted because it was unlinked, and what's left is a changed file with the same name as the original. 最后,旧文件被关闭,因此被删除,因为它是未链接的,剩下的是一个与原始文件同名的更改文件。

See also doio.c for actual implementation. 有关实际实现,另请参见doio.c.

  • According to the above, the following might work: 根据以上所述,以下可能有效:

     my $fn = 'test.dat'; open ( my $fh, '<:raw', $fn ) or die "Could not open file '$fn': $!"; unlink $fn or die "$!"; open ( my $fh2, '>:raw', $fn ) or die "Could not reopen file '$fn': $!"; while(<$fh>) { # Do the substitutions on $_ here ... print $fh2 $_; } close $fh; close $fh2; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM