在Perl One Liner中,我们可以使用-i参数进行就地替换。在IDE中编写Perl代码时,-i有什么等效功能?

考虑以下代码:

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;

}

我们如何才能将所有更改行保存到位?

因为我需要在就地更改html源代码后立即使用XML::LibXML对html文件进行快速验证。

提前致谢。

最佳答案

您可以尝试如下操作:

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

我没有找到如何在循环之前设置binmode的方法,因为ARGV仅在使用<>运算符之后才定义。
  • $^I ARGV变量在perlop中描述
  • 有关为什么应使用perlvar而不是<<>>的信息,请参见perlop

  • 一些注意事项:
  • <>根据perlrun,循环
  • while (<>) {  ...         # code for each line
    }
    

    等效于以下类似Perl的伪代码:
    unshift(@ARGV, '-') unless @ARGV;
    while ($ARGV = shift) {
        open(ARGV, $ARGV);
        while (<ARGV>) {
           ...        # code for each line
        }
    }
    
  • 在不使用备份文件的情况下使用就地编辑:while(<>) { ... }:

  • 根据this:

    如果没有提供扩展名,并且您的系统支持该扩展名,则原始
    在输出重定向到
    具有原始文件名的新文件。无论Perl是否干净地退出,
    原始文件已取消链接。

    以及doio.c博客中的更多信息:

    Perl打开,并立即取消链接原始文件,然后打开一个
    具有相同名称的新文件(新文件描述符和索引节点),并发送
    输出到第二个文件;最后,关闭旧文件,
    由于已取消链接而被删除,剩下的就是更改
    与原始文件同名的文件。

    有关实际实现,另请参见ojit_a。
  • 根据以上所述,可能会执行以下操作:
    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;
    
  • 09-25 21:18