人们一直在问这个问题,我一直用perlfaq5的相同答案回答这个问题.现在,我们可以在Stackoverflow上指出这一点.
bri*_*foy 13
来自perlfaq5:
从文本文件中插入,更改或删除行的基本思想包括读取和打印文件到要进行更改的位置,进行更改,然后读取和打印文件的其余部分.Perl不提供对行的随机访问(特别是因为记录输入分隔符$/
,是可变的),尽管诸如Tie :: File之类的模块可以伪造它.
执行这些任务的Perl程序采用打开文件,打印其行,然后关闭文件的基本形式:
open my $in, '<', $file or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";
while( <$in> )
{
print $out $_;
}
close $out;
Run Code Online (Sandbox Code Playgroud)
在该基本表单中,添加您需要插入,更改或删除行的部分.
要将行添加到开头,请在进入打印现有行的循环之前打印这些行.
open my $in, '<', $file or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";
print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC
while( <$in> )
{
print $out $_;
}
close $out;
Run Code Online (Sandbox Code Playgroud)
要更改现有行,请插入代码以修改while
循环内的行.在这种情况下,代码找到所有小写版本的"perl"并将它们大写.它发生在每一行,所以请确保你应该在每一行都这样做!
open my $in, '<', $file or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";
print $out "# Add this line to the top\n";
while( <$in> )
{
s/\b(perl)\b/Perl/g;
print $out $_;
}
close $out;
Run Code Online (Sandbox Code Playgroud)
要仅更改特定行,输入行号$.
很有用.首先阅读并打印到您想要更改的行.接下来,阅读您要更改的单行,更改并打印它.之后,阅读其余部分并打印出来:
while( <$in> ) # print the lines before the change
{
print $out $_;
last if $. == 4; # line number before change
}
my $line = <$in>;
$line =~ s/\b(perl)\b/Perl/g;
print $out $line;
while( <$in> ) # print the rest of the lines
{
print $out $_;
}
Run Code Online (Sandbox Code Playgroud)
要跳过行,请使用循环控件.所述next
在该实施例中跳过的注释行和last
停止所有处理一旦遇到任一__END__
或__DATA__
.
while( <$in> )
{
next if /^\s+#/; # skip comment lines
last if /^__(END|DATA)__$/; # stop at end of code marker
print $out $_;
}
Run Code Online (Sandbox Code Playgroud)
通过使用next
跳过不想在输出中显示的行来删除特定行也是同样的事情.此示例跳过每五行:
while( <$in> )
{
next unless $. % 5;
print $out $_;
}
Run Code Online (Sandbox Code Playgroud)
如果由于一些奇怪的原因,你真的想要一次看到整个文件而不是逐行处理,你可以将它啜饮(只要你能将整个文件放在内存中!):
open my $in, '<', $file or die "Can't read old file: $!"
open my $out, '>', "$file.new" or die "Can't write new file: $!";
my @lines = do { local $/; <$in> }; # slurp!
# do your magic here
print $out @lines;
Run Code Online (Sandbox Code Playgroud)
File :: Slurp和Tie :: File等模块也可以提供帮助.但是,如果可以,请避免立即读取整个文件.在该过程完成之前,Perl不会将该内存返回给操作系统.
您还可以使用Perl单行来就地修改文件.以下内容将所有'Fred'更改为'Barney' inFile.txt
,用新内容覆盖文件.使用该-p
开关,Perl while
围绕您指定的代码包装一个循环-e
,并-i
打开就地编辑.目前的行是在$_
.使用-p
,Perl会自动打印$_
循环结束时的值.有关详细信息,请参阅perlrun.
perl -pi -e 's/Fred/Barney/' inFile.txt
Run Code Online (Sandbox Code Playgroud)
要进行备份inFile.txt
,请提供-i
要添加的文件扩展名:
perl -pi.bak -e 's/Fred/Barney/' inFile.txt
Run Code Online (Sandbox Code Playgroud)
要仅更改第五行,可以添加测试检查$.
,输入行号,然后仅在测试通过时执行操作:
perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt
Run Code Online (Sandbox Code Playgroud)
要在某一行之前添加行,可以在Perl打印之前添加一行(或多行!)$_
:
perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt
Run Code Online (Sandbox Code Playgroud)
您甚至可以在文件的开头添加一行,因为当前行在循环结束时打印:
perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt
Run Code Online (Sandbox Code Playgroud)
要在文件中已有的行之后插入一行,请使用该-n
开关.它就像-p
它$_
在循环结束时不打印一样,所以你必须自己做.在这种情况下,$_
首先打印,然后打印要添加的行.
perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt
Run Code Online (Sandbox Code Playgroud)
要删除行,只打印您想要的行.
perl -ni -e 'print unless /d/' inFile.txt
... or ...
perl -pi -e 'next unless /d/' inFile.txt
Run Code Online (Sandbox Code Playgroud)