我经常使用
perl -pi -w -e 's/search/replace/g;' [filelist]
在[filelist]的所有文件中用“replace”替换“search”的每个外观。不幸的是,所有文件似乎都获得了更新的时间戳。即使“搜索”没有出现在文件中。我可以改变这是一种简单的方法吗?
答案 0 :(得分:2)
不容易,不。所有发生的事情都是perl正在覆盖文件,结果是通过正则表达式。
你可以使用更长的程序来完成它,但是没有简单的标志可以阻止这种行为。
答案 1 :(得分:1)
-i[*extension*]
指定由“
<>
”构造处理的文件 就地编辑。它通过重命名输入文件来打开 输出文件的原始名称,并选择该输出 file作为print()
语句的默认值。扩展,如果 提供,用于修改旧文件的名称 备份副本,遵循以下规则:如果未提供扩展,则不进行备份和当前文件 被覆盖。
强调我的。
要解决此问题,您需要编写一个程序,为@ARGV
中的每个文件打开一个临时文件,从原始文件中读取,进行替换,将行写入临时文件,以及跟踪是否有任何替换改变了原始行。到达文件末尾时,如果任何s///
调用导致更改,它会将临时文件重命名为原始文件。 eof对此以及File::Temp模块都很有用。
答案 2 :(得分:1)
-i
是松散的:
rename($ARGV, "$ARGV$^I") or die $! if length $^I;
open(*ARGV, '<', "$ARGV$^I") or die $!;
open(*STDOUT, '>', $ARGV) or die $!;
正如您所看到的,它总是立即取代现有文件。这就是所有打印(-p
)发送输出的地方。
两个选项:
使用临时文件。
perl -e'
$temp_qfn = "temp";
open(my $fh_out, ">", $temp_qfn) or die $!;
my $save;
while (<>) {
$save = 1 if s/search/replace/g;
print($fh_out $_);
} continue {
if (eof) { # Not eof()!
close($fh_out);
rename($temp_qfn, $ARGV) if $save;
$save = 0;
open(my $fh_out, ">", $temp_qfn) or die $!;
}
}
close($fh_out);
unlink($temp_qfn);
' file ...
将整个文件加载到内存中。
perl -0777ne'
if (s/search/replace/g) {
open(my $fh_out, ">", $ARGV) or die $!;
print($fh_out $_);
}
' file ...
(以上两种都有各种可解决的错误处理问题。-i
有一些相同的问题。)