在 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 定义的行为是就地编辑文件,不创建备份文件:If no extension is supplied, and your system supports it, the original file is kept open without a name while the output is redirected to a new file with the original filename. When perl exits, cleanly or not, the original file is unlinked.
也许我的系统(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?当然,“并且您的系统支持它”子句意味着该示例没有错,但如果该示例也涵盖了这种情况,则会更有用。 最佳答案
Perl 5.28 changed -i
.此答案适用于早期版本的 Perl。
当提供扩展时:
open(my $fh_in, '<', $qfn);
rename($qfn, "$qfn$ext");
open(my $fh_out, '>', $qfn);
这可以使用
strace
看到.$ strace perl -i~ -pe1 a
...
open("a", O_RDONLY) = 3
rename("a", "a~") = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
...
当没有提供扩展名时:
open(my $fh_in, '<', $qfn);
unlink($qfn);
open(my $fh_out, '>', $qfn);
这可以使用
strace
看到.$ strace perl -i -pe1 a
...
open("a", O_RDONLY) = 3
unlink("a") = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
...
Mac 等 Unix 系统支持匿名文件。 Windows 没有,所以
-i
需要在那里扩展。>perl -i.bak -pe1 a
>perl -i -pe1 a
Can't do inplace edit without backup.
如果我们将这些知识整合到您发布的代码中,我们将得到以下信息:
#!/usr/bin/perl
use strict;
use warnings;
my $extension = '.orig';
my $oldargv = '';
my $backup;
LINE: while (<>) {
if ($ARGV ne $oldargv) {
if (length($extension)) {
if ($extension !~ /\*/) {
$backup = $ARGV . $extension;
} else {
($backup = $extension) =~ s/\*/$ARGV/g;
}
rename($ARGV, $backup);
} else {
die("Can't do inplace edit without backup.\n") if $^O eq 'MSWin32';
unlink($ARGV);
}
open(ARGVOUT, ">$ARGV");
select(ARGVOUT);
$oldargv = $ARGV;
}
# Don't change anything; just copy.
}
continue {
print;
}
select(STDOUT);
关于perl - perl -i *really* 是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30538865/