【发布时间】:2015-05-29 20:52:52
【问题描述】:
在http://perldoc.perl.org/perlrun.html 对 Perl -i[extension] 功能的描述中,与以下程序基本相同的代码被视为使用 perl -pi.orig ... 的“等价物”:
#!/usr/bin/perl
use strict;
use warnings;
my $extension = '.orig';
my $oldargv = '';
my $backup;
LINE: while (<>) {
if ($ARGV ne $oldargv) {
if ($extension !~ /\*/) {
$backup = $ARGV . $extension;
} else {
($backup = $extension) =~ s/\*/$ARGV/g;
}
rename($ARGV, $backup);
open(ARGVOUT, ">$ARGV");
select(ARGVOUT);
$oldargv = $ARGV;
}
# Don't change anything; just copy.
}
continue {
print;
}
select(STDOUT);
$extension eq '.orig' 时这工作正常;然而,Perl 也定义了没有扩展名的-i(即$extension eq '')。 Perl 定义的行为是在原地编辑文件,而不创建备份文件:
如果没有提供扩展,并且您的系统支持它,则原来的 当输出被重定向到一个 具有原始文件名的新文件。当 perl 退出时,无论是否干净, 原始文件已取消链接。
也许我的系统(Mac OS X Yosemite 10.10.3)不支持它。
如果我在这个程序中设置$extension = '',那么代码对于小于一个 STDIN 块的文件(AcivePerl 5.10 中为 4096 字节,而 ActivePerl 5.16 中为 8192 字节)将正常工作,但它会不 适用于大于 1 块的文件。
在我看来,在我的系统上,如果 $ARGV 和 $backup 具有相同的值(如果 $extension eq '' 相同,那么第 17 行上的 open(ARGVOUT, ">$ARGV") 调用会在一个块之后破坏输入文件已阅读。
当然,我可以通过写入一个临时文件然后在最后重命名它来解决这个问题。但是我有点失望,经过几个小时的调试,perlrun 中的示例没有我预期的那样通用。
是否有标准、惯用的方法来处理
$extension eq ''案例?这个
$extension eq ''用例是否足够重要以至于应该编辑perlrun?当然,“and your system supports it”子句表示这个例子没有错,但是如果这个例子也能涵盖这种情况会更有用。
【问题讨论】:
-
示例程序正确的原因是示例程序是关于
-i.orig,而不是关于没有扩展名的-i。如果您只是删除程序中的.orig,我不知道您为什么希望示例程序的行为类似于-i。 (这就像看到5 * 5 == 25并因此假设8 * 8 == 28。)它的正确性与“并且您的系统支持它”子句无关,这是关于您的系统是否支持保持未链接文件的打开句柄。 -
(顺便说一下,它不是
-i '',而是没有参数的裸-i。字符串比较使用eq,而不是==。) -
虽然你可以写
-i''. -
@ruakh,我对你关于
5 * 5的观点很敏感,但这是一个应该展示 Perl 工作原理的示例,我不认为有这种感觉是不合理的这个例子有点误导。按照您的类比,就好像您告诉我,(a, b) = (5, 5)的某些功能f(a, b)与代码a * b“等效”,但没有提到当a和b有其他代码时代码是不同的允许值。 -
没有。它应该显示
perl -p -i.orig -e 's/foo/bar/;'的工作原理。