读取一个文件并修改它

Read a file and modify it

我正在尝试处理数据流。

首先我将一个文本文件添加到我的脚本中。

文本文件是这样的:

pierwsza linia  koniec
druga linia lorem1 koniec lorem1 lorem1
trzecia linia lorem1 koniec lorem1
czwarta linia lorem1 koniec
piata liniakoniec
szosta linia lorem1 koniec

我想要实现的是一个包含所有行但只有第一次出现 lorem1.

的文件

所以预期的结果应该是这样的

pierwsza linia  koniec
druga linia lorem1 koniec
trzecia linia koniec
czwarta linia koniec
piata liniakoniec
szosta linia koniec

我的脚本是这样的

#!/usr/bin/perl -pi

use strict;

my $line = $_;
my $loremcn;

while ( $line = <> ) {

    #if ( $line =~ m/lorem1/ )

    foreach ( $line =~ m/lorem1/gi ) {

        $loremcn++;

        if ( $loremcn >= 2 ) {
            $line =~ s/lorem1//gi;
        }

        print "$loremcn\n";
        print $line;

        chomp $line;
    }
}

但是结果只是文本的第一行(因为脚本开头的 -pi)。

该脚本正确计算了 lorem1 (7) 的出现次数,但由于 /g 选项,它删除了所有 lorem1 的出现次数(它不会单独留下第一个)。

最后,最后如何将整条更正后的文字打印到屏幕上?

更新

我对其中一个答案写了这条重要评论:

In RL I cannot do this Your way. This whole excercise is to find a way on how to do this with streamed data. In true scenario the whole data is not from opened text, but it's a spool data streamed to printer from SAP. And that data needs to be corrected on the way to the printer

#!/usr/bin/perl 
use strict;
use warnings;

# lorem counter
my $loremcn = 0;
# loop over the input file
while (my $line = <> ) {
    # if line contains lorem1 but not alorem1 or lorem12
    if ($line =~ /\blorem1\b/i) {
        # not the first time. counter > 0
        if ($loremcn) {
            # remove all lorem1 and optional leading horizontal spaces
            $line =~ s/\h*\blorem1\b//gi;   # comment for syntax color /
        # first time lorem1 is encountered (counter == 0)
        } else {
            # remove all lorem1 but the first
        while ($line =~ s/
                            (\blorem1\b.*?)     # first lorem1 in the line followed by 0 or more anycharacter
                            \blorem1\b          # subsequent lorem1
                            //gix             # replace with the first group (i.e. the first lorem1
            ) { 1;}
        }
        # incement counter
        $loremcn++;
    }
    # print the modified line
    print $line;
}

输出:

pierwsza linia  koniec
druga linia lorem1 koniec  
trzecia linia koniec
czwarta linia koniec
piata liniakoniec
szosta linia koniec

用法:

perl test.pl inputfile > outputfile

不就是这个吗?

my $seen;
while (<>) {
  s/\blorem1\b//g if $seen;
  $seen = 1 if /\blorem1\b/;
  print;
}

更新: 好吧,比我原先想象的要复杂一点。但这似乎可以满足您的要求:

#!/usr/bin/perl

use strict;
use warnings;

my $seen;

while (<>) {
  if ($seen) {
    s/\blorem1\b//g;
  } else {
    1 while s/(?<=\blorem1\b)(.*)\blorem1\b//g;
    $seen = 1 if /\blorem1\b/;
  }
  print;
}

运行 你的代码 B::Deparse 像这样

perl -MO=Deparse xx.pl

给出这个结果

BEGIN { $^I = ""; }   # From -i

LINE: while (defined($_ = readline ARGV)) {


    use strict;
    my $line = $_;
    my $loremcn;
    while (defined($line = readline ARGV)) {
        foreach $_ ($line =~ /lorem1/gi) {
            ++$loremcn;
            if ($loremcn >= 2) {
                $line =~ s/lorem1//gi;
            }
            print "$loremcn\n";
            print $line;
            chomp $line;
        }
    }


}
continue {
    die "-p destination: $!\n" unless print $_;
}

所以您看到您的代码中有 两个 while 循环:您不应该将命令行选项与程序文件混淆,因此可能不明显

这是一种实现我认为您想要的方法。它使用你的全局计数器 $loremcn 和一个 表达式 全局替换来替换 lorem1 在第一个实例

之后什么都没有
#!/usr/bin/perl

use strict;
use warnings 'all';

@ARGV = 'file1.txt';

my $loremcn = 0;

while ( <> ) {

    s{(\blorem1\b[ \t]*)}{ $loremcn++ ? '' :  }ge;

    print;
}

输出

pierwsza linia  koniec
druga linia lorem1 koniec 
trzecia linia koniec 
czwarta linia koniec
piata liniakoniec
szosta linia koniec

一个衬垫使用 perl:

您可以保留第一个 lorem 之前的所有内容,然后删除此之后的所有 lorem,即

 $perl -pe "undef $/;s/^.*?\blorem1\K|\blorem1//g" lorem.txt
  • \b - 用于确定边界。
  • .*?- 非贪婪匹配。将所有内容都匹配到第二个 lorem
  • \K - 丢弃任何之前消耗的字符。因此从第二个lorem删除到最后

输出

pierwsza linia  koniec
druga linia lorem1 koniec
trzecia linia  koniec
czwarta linia  koniec
piata liniakoniec
szosta linia  koniec

现在如果你想把它保存在另一个文件中,你可以这样做:

perl -pe "undef $/;s/^.*?\blorem1\K|\blorem1//g" lorem.txt > new_file.txt

如果你的perl版本不支持\K,你可以使用:

 perl -pe "undef $/;s/(^.*?\blorem1)|\blorem1//g" lorem.txt