我正在尝试处理数据流。
首先,我将一个文本文件添加到脚本中。
文本文件如下:
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流到打印机的后台打印数据。而且该数据需要在送往打印机的途中进行纠正
答案 0 :(得分:2)
#!/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
答案 1 :(得分:1)
使用perl
的班轮:
您可以保留所有内容,直到第一个lorem,然后在此之后删除所有lorem,即
$perl -pe "undef $/;s/^.*?\blorem1\K|\blorem1//g" lorem.txt
\b
-用于确定边界。.*?
-非贪婪匹配。将所有内容匹配到第二个lorem
\K
-丢弃以前使用的所有字符。因此,从第二个lore删除到最后输出
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
答案 2 :(得分:0)
不仅仅是这个吗?
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;
}
答案 3 :(得分:-1)
使用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
和 expression 全局替换,以在第一个实例之后用任何内容替换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