perl - 如何使用 Perl 替换文件中间的行?

标签 perl file text replace append

我正在以 append 模式打开文件。我需要替换文件中的第 2,3 和 4 行,稍后我需要在文件末尾添加新数据。

最佳答案

我认为这是我在 Stackoverflow 上转发次数最多的常见问题解答。 perlfaq5答案为How do I change, delete, or insert a line in a file, or append to the beginning of a file? .

忘记 append 模式的东西。这只会让你的生活变得更加艰难。

<小时/>

从文本文件中插入、更改或删除行的基本思想包括读取和打印文件到要进行更改的位置,进行更改,然后读取和打印文件的其余部分。 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;

要仅更改特定行,the input line number, $. ,很有用。首先阅读并打印直到您要更改的行。接下来,读取要更改的单行,更改它,然后打印它。之后,阅读其余行并打印它们:

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::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 - 如何使用 Perl 替换文件中间的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2278527/

相关文章:

java - 将文件合并成一个新的大文件,直到用户id的数量达到1000万

text - Haskell、Char、Unicode 和土耳其语

windows - 如何从 perl 启动程序?

perl - 如何重构 for 循环中发生的递归以使其成为尾调用?

regex - 使用正则表达式在 Perl 中计算句子/单词

java - 如何删除临时文件?

php - 什么会更好 : click counter on mysql or on flat file?

macos - 在 Mac OS X Firefox 上无法选择 CSS3 @font-face

Python将文本分割成x个字符的 block

arrays - Moose 阵列属性 : how do I use a set method?