我正在尝试处理数据流。
首先,我将一个文本文件添加到我的脚本中。
文本文件如下:
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
事件(它不会留下第一个单独)。
最后,如何将整个修正后的文本打印到屏幕上?
我在其中一个答案上写了这个重要的评论:
在RL我不能这样做。这整个练习是为了找到一种如何使用流数据执行此操作的方法。在真实场景中,整个数据不是来自打开的文本,而是从SAP流式传输到打印机的假脱机数据。并且该数据需要在去往打印机的途中得到纠正
#!/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
/$1/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
使用perl
的一个班轮:
您可以保留所有内容,直到第一个lorem然后删除所有的lorems,即
$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/$1/g" lorem.txt
不就是这个吗?
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/$1/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++ ? '' : $1 }ge;
print;
}
pierwsza linia koniec
druga linia lorem1 koniec
trzecia linia koniec
czwarta linia koniec
piata liniakoniec
szosta linia koniec