在Perl的-i[extension]特性描述中,网址为http://perldoc.perl.org/perlrun.html,与使用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退出时,无论是干净地还是不干净地,原始文件都将被取消链接。
也许我的系统(Mac OS X Yosemite 10.10.3)不支持它。
如果我在此程序中设置$extension = ''
,则该代码对小于STDIN块的文件(在AcivePerl 5.10中为4096字节,但在ActivePerl 5.16中为8192字节)可以正常工作,但对于大于一个块的文件则不会正常工作。
在我的系统中,如果$ARGV
和$backup
具有相同的值(如果$extension eq ''
,则它们将是相同的),那么第17行的open(ARGVOUT, ">$ARGV")
调用会在读取一个块后破坏输入文件。
当然,我可以通过先写入临时文件,然后在最后重命名来解决这个问题。但是,经过几个小时的调试后,我有点失望,因为perlrun中的示例并不像我预期的那样通用。
是否有一种标准的惯用方法来处理
$extension eq ''
的情况?这个
$extension eq ''
的用例是否足够重要,以至于需要编辑perlrun?当然,“如果您的系统支持它”这个条件意味着示例不是不正确的,但如果也涵盖了这种情况,那么示例将更有用。
-i.orig
而不是没有扩展名的-i
。如果您仅仅删除程序中的.orig
,就期望示例程序表现得像-i
一样,我不知道您为什么会有这个期望。(这就像看到5 * 5 == 25
,然后假设8 * 8 == 28
)它的正确性与“你的系统支持它”这个条件无关,后者是指您的系统是否支持保持对已取消链接文件的打开句柄。 - ruakh-i''
,而是没有参数的裸-i
。字符串比较使用eq
而不是==
。 - ruakh-i''
。 - ikegami5 * 5
的观点,但这只是一个展示Perl工作原理的例子,我认为对这个例子感到有些误导并不是不合理的。按照你的比喻,这就好像你告诉我一些函数f(a, b)
在(a, b) = (5, 5)
时“等同于”代码a * b
,但没有提到当a
和b
具有其他可允许值时代码是不同的。 - Cary Millsap-i
是如何工作的?如果是前者,你可以在 shebang 行上包含标志,例如#!/usr/bin/perl -pi
。 - ThisSuitIsBlackNotperl -p -i.orig -e 's/foo/bar/;'
的工作原理。 - ikegami