【问题标题】:How do I change, delete, or insert a line in a file, or append to the beginning of a file in Perl?如何在 Perl 中更改、删除或插入文件中的一行,或附加到文件的开头?
【发布时间】:2011-01-20 07:08:42
【问题描述】:

人们一直在问这个问题,我一直在用来自perlfaq5 的相同答案来回答它。现在我们可以在 Stackoverflow 上指出这一点。

【问题讨论】:

  • 在这里转发perlfaqN 有什么意义?你不能给提问者一个perfaq5perldoc.perl.org/…的链接吗?
  • 我一直讨厌链接。网站过时,URL 更改等。我认为 Stackoverflow 应该捕获信息,以便它始终拥有它。请记住,这是一个长期项目,三年后答案应该和现在一样好。链接并不能保证这一点。请记住,在消失之前,www.perldoc.com 曾经是文档的首选站点。这可能发生在任何网站上。
  • 另外,请参阅我询问导入所有 perlfaq 的元线程:meta.stackexchange.com/questions/24244/…
  • @brian 你收到 StackOverflow 团队关于 perlfaq 导入的官方回复了吗?
  • 我认为 Jeff 会听从人们的决定。我只是还没来得及做。

标签: perl file


【解决方案1】:

来自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;

在该基本表单中,添加您需要插入、更改或删除行的部分。

要将行添加到开头,请在进入打印现有行的循环之前打印这些行。

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 $_;
    }

要跳过行,请使用循环控件。本例中的next 跳过注释行,last 在遇到__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::SlurpTie::File 等模块也可以提供帮助。但是,如果可以,请避免一次读取整个文件。在进程完成之前,Perl 不会将该内存归还给操作系统。

您还可以使用 Perl 单行代码就地修改文件。以下将inFile.txt 中的所有“Fred”更改为“Barney”,用新内容覆盖文件。使用-p 开关,Perl 围绕您使用-e 指定的代码包装了一个while 循环,-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

    ... or ...

perl -pi -e 'next unless /d/' inFile.txt

【讨论】:

  • 只是想知道,为什么我们写perl -pie...时它不起作用?
  • -pie 不起作用,因为 -i 需要一个参数,并且它认为 'e' 属于它。
  • 最后一个变体:perl -pi -e 'next unless /d/' inFile.txt 不起作用,并且不再显示在perlfaq 中。 cmets中的一些讨论here
猜你喜欢
  • 2011-05-22
  • 2021-10-19
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
相关资源
最近更新 更多