在 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 一行 + 如何仅在完全匹配时替换文件中的路径

在 Perl 中,如何在没有轮询但有超时的情况下监视文件更改?

InnoDB怎么可能在一行上死锁?

matlab中如何给已有矩阵插入一行或一列值

Linux下在文件内部指定行插入或删除内容

如何从 Perl 中的一行中提取非空白组?