在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;