从perlfaq5的答案How do I change, delete, or insert a line in a file, or append to the beginning of a file?
从一个文本文件中插入,更改或删除线的基本思想包括阅读并将文件打印到您想要进行更改的位置,进行更改,然后阅读并打印文件的其余部分乐。 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 $_;
}
接近$出; 在该基本表单中,添加您需要插入,更改或删除行的部分。
要在行首添加行,请在输入打印现有行的循环之前打印这些行。
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; 要更改现有行,请插入代码以修改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; 要仅更改特定行,输入行号$。是有用的。首先阅读并打印您想要更改的行。接下来,阅读您想要更改的单行,更改并打印它。之后,阅读其余的行并打印这些行:
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 $_;
}
要跳过行,请使用循环控制。本例中的下一个跳过注释行,并且一旦遇到END或DATA,最后一次停止所有处理。
while(<$in>)
{
next if /^\s+#/; # skip comment lines
last if /^__(END|DATA)__$/; # stop at end of code marker
print $out $_;
}
做同样的事情来删除一个特定的行,使用next来跳过你不想显示在输出中的行。只要
while(<$in>)
{
next unless $. % 5;
print $out $_;
}
如果出于某种奇怪的原因,你真的想看到整个文件一次,而不是加工生产线,由线,您可以在思乐普它(如你:这个例如每第五行跳过可以容纳在内存中的整个事情)!
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;
模块如File :: Slurp的和领带::文件可以提供帮助的了。但是,如果可以,请避免一次读取整个文件。在这个过程完成之前,Perl不会将该内存返回给操作系统。
您还可以使用Perl one-liners来就地修改文件。以下内容将inFile.txt中的所有'Fred'更改为'Barney',并用新内容覆盖文件。使用-p开关,Perl将用-e指定的代码包装一个while循环,并且-i打开就地编辑。当前行在$ 。使用-p,Perl会在循环结束时自动打印$的值。有关更多详细信息,请参阅perlrun。
perl -pi -e 's/Fred/Barney/' inFile.txt
为了inFile.txt的备份,给-ia文件扩展名补充:
perl -pi.bak -e 's/Fred/Barney/' inFile.txt
要改变只有第五行,你可以添加一个测试检查$,输入线。数,则只有当测试通过执行操作:
perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt
在一定行之前添加行,你可以添加一行的Perl打印$ _之前(或行!):
perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt
你甚至可以在循环的末尾添加一行到文件的开头,因为当前行打印:
perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt
已经在文件中,使用一个后插入一行-n开关。它就像-p,除了在循环结束时不打印$ _,所以你必须自己做。在这种情况下,首先打印$ _,然后打印要添加的行。
perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt
要删除行,只打印所需的行。
perl -ni -e 'print unless /d/' inFile.txt
... or ...
perl -pi -e 'next unless /d/' inFile.txt
您可能想要为该第二个正则表达式添加'/ i'修饰符以及... – 2010-02-22 22:48:56
谢谢!唯一缺少的是在'if'语句中的'$ fho'后面的'$ _'(花了我一段时间才发现,实际上...) – ryantmer 2010-02-22 22:55:19
@ryantmer:是的,我的代码没有经过测试。我更新了我的帖子。我懒得创建任何虚假输入来测试我的代码,这就是为什么提供一个小样本输入与您的问题是一个好主意。 – toolic 2010-02-22 23:41:50