在 Perl 中,如何在文件中更改、删除或插入一行,或追加到文件的开头?
Posted
技术标签:
【中文标题】在 Perl 中,如何在文件中更改、删除或插入一行,或追加到文件的开头?【英文标题】:In Perl, how do I change, delete, or insert a line in a file, or append to the beginning of a file? 【发布时间】:2011-05-22 06:12:38 【问题描述】:我想通过修改、删除或插入行或附加到文件的开头来更改文件的内容。如何在 Perl 中做到这一点?
这是来自official FAQ 的question。我们是importing the perlfaq to Stack Overflow。
【问题讨论】:
How do I change, delete, or insert a line in a file, or append to the beginning of a file in Perl?的可能重复 【参考方案1】:(这是official perlfaq answer,减去任何后续编辑)
在文本文件中插入、更改或删除一行的基本思想
涉及读取文件并将其打印到您想要的位置
更改,进行更改,然后读取并打印文件的其余部分。
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;
在该基本表单中,添加您需要插入、更改或 删除行。
要将行添加到开头,请在输入之前打印这些行 打印现有行的循环。
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等模块 Tie::File 可以提供帮助 也。但是,如果可以,请避免一次读取整个文件。 Perl 不会 将该内存还给操作系统,直到进程完成。
您还可以使用 Perl 单行代码就地修改文件。下列
将 inFile.txt 中的所有“Fred”更改为“Barney”,用
新内容。使用-p
开关,Perl 在代码周围包裹了一个 while 循环
您使用-e
指定,-i
将打开就地编辑。目前的
行在$_
。使用-p
,Perl 自动打印$_
的值
循环结束。详情请见perlrun。
perl -pi -e 's/Fred/Barney/' inFile.txt
要备份 inFile.txt,请给 -i 一个要添加的文件扩展名:
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
【讨论】:
perl -ni -e 'print unless /d/' inFile.txt
确实可以删除匹配的行,但perl -pi -e 'next unless /d/' inFile.txt
没有。也没有将next unless
更改为next if
。这是 perl 5.10.0。知道发生了什么吗?
@TreborRude,即使perl -pi -e 'next'
打印文件不变(而不是跳过所有数据)确实是最后打印,但根据perlrun
它在continue
块内,因此无论如何都会执行(perldoc.perl.org/functions/continue.html)。下一个/除非变体也不在当前的perlfaq5
以上是关于在 Perl 中,如何在文件中更改、删除或插入一行,或追加到文件的开头?的主要内容,如果未能解决你的问题,请参考以下文章
sed 或 Perl 一行 + 如何仅在完全匹配时替换文件中的路径