我在一个perl脚本中嵌入了一个perl一行程序,其目的是为扩展名为.ini的文件的每一行就地将一个字符串替换为另一个字符串,但是我发现每个文件都是用.bak备份的。
因为在一行程序中,我只指定了-i
而不是-i.bak
,所以我想知道为什么会生成.bak文件。
foreach my $dir (glob "*.ini") {
system qq(perl -i -pe 's|Default|UTF-8|' $dir);
}
另一个问题是,是否有更好、更简洁的perl脚本来实现相同的目标(无需备份.bak文件),无论是否使用一行程序。
发布于 2016-07-19 13:25:16
我想你可能正在看一些旧的数据文件。据我所知,Perl在任何情况下都不会假定默认文件扩展名为.bak
如果您将该选项指定为just -i
,那么它将尝试就地编辑文件,方法是在打开输入文件后将其删除并创建一个同名的新输出文件。旧文件在关闭之前一直保持可读状态
这种技术在Windows上不起作用,因此在该平台上使用纯-i
选项是错误的
没有必要仅仅为了编辑一些文件而将shell转到第二个perl进程。它可以像这样非常简单地完成。内部变量$^I
对应于命令行上的-i
选项的值。同样,如果您使用的是Windows系统,则$^I
可能不是空字符串,您需要将其设置为.bak
或类似的值
{
local @ARGV = glob 'f.*';
local $^I = ''; # Must be non-blank on Windows
while ( <> ) {
s/Default/UTF-8/g;
print;
}
}
发布于 2016-07-19 12:55:55
这里有一种方法可以做到这一点,而不必编写另一个perl实例。此技术使用中间临时文件:
use warnings;
use strict;
for my $file (glob "*.ini") {
open my $fh, '<', $file or die $!;
open my $wfh, '>', 'temp.txt' or die $!;
while (<$fh>){
s/Default/UTF-8/;
print $wfh $_;
}
close $fh;
close $wfh;
unlink $file or die $!;
rename 'temp.txt', $file;
}
如果您知道您的文件不会太大,请使用此版本。它将整个文件读取到内存中(单个字符串标量),并且不需要中间临时文件:
use warnings;
use strict;
for my $file (glob "*.ini") {
open my $fh, '<', $file or die $!;
my $contents;
{
local $/;
$contents = <$fh>;
}
close $fh;
$contents =~ s/Default/UTF-8/;
open my $wfh, '>', $file or die $!;
print $wfh $contents;
close $wfh;
}
发布于 2016-07-19 13:58:56
我认为bash命令find + xargs和perl应该比perl循环更容易。
find . -name '*.ini' |xargs perl -pi -e 's/Default/UTF-8/g'
https://stackoverflow.com/questions/38458953
复制