查找以零结尾的行并打印其姐妹行

时间:2013-05-04 17:15:18

标签: perl sed awk

我的文件包含以下行:

Data;moreData;EvenMoreData1;200
Data;moreData;EvenMoreData1;200

Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0

Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

基本上每2条线彼此相关。我试图找到最好的方法,只用一个0和它上面或下面的线打印线。所以输出就像。

Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0

Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

4 个答案:

答案 0 :(得分:7)

$ perl -00 -ne "print if /;0$/m;" < input
0;Data;0;moreData;EvenMoreData2;500
0;Data;0;moreData;EvenMoreData2;0

0;Data;0;moreData;EvenMoreData3;0
0;Data;0;moreData;EvenMoreData3;0

0;Data;0;moreData;EvenMoreData3;0
0;Data;0;moreData;EvenMoreData3;1

-00打开段落模式,将输入记录分隔符设置为\n\n+,因此这取决于两条数据行之间的空行。

$ cat input
0;Data;0;moreData;EvenMoreData1;200
0;Data;0;moreData;EvenMoreData1;200

0;Data;0;moreData;EvenMoreData2;500
0;Data;0;moreData;EvenMoreData2;0

0;Data;0;moreData;EvenMoreData3;0
0;Data;0;moreData;EvenMoreData3;0

0;Data;0;moreData;EvenMoreData3;0
0;Data;0;moreData;EvenMoreData3;1

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed -r 'N;N;/;0(\n|$)/p;d' file

答案 2 :(得分:1)

告诉awk记录是用空行(-v RS=)分隔的,字段是换行符(-F'\n'),然后检查记录中任何一行末尾的“; 0”: / p>

$ awk -v RS= -v ORS='\n\n' -F'\n' '/;0(\n|$)/' file
Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0

Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

将ORS设置为2个换行符(-v ORS='\n\n')只是告诉awk在输出记录之间放置一个空行,使其看起来像您的输入格式。如果您不关心这一点,只需不要设置ORS,您就会变得更简单:

$ awk -v RS= -F'\n' '/;0(\n|$)/' file
Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0
Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

仅供参考,这将适用于您记录中任意数量的行。

回应评论要求进一步解释:

awk是基于记录的,与基于行的sed不同。 awk的默认记录分隔符是换行符,因此默认情况下awk在行上工作,就像sed一样,但是通过更改记录分隔符(内置RS变量),您可以使用awk处理您喜欢的任何文本块。特别是当您将RS设置为NULL字符串时,awk记录由空行分隔。

因此,在这种特殊情况下,-v RS=将RS设置为NULL字符串,因此awk将输入处理为3条记录:

记录1)

Data;moreData;EvenMoreData1;200
Data;moreData;EvenMoreData1;200

记录2)

Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0

记录3)

Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

dafault的awk将记录分成由白色空间链分隔的字段,但您可以通过设置内置字段分隔符变量FS来改变该行为。在这种情况下,我通过执行-F'\n'将FS设置为换行符,这意味着上述每条记录都被视为2个字段:

记录1,字段1)

Data;moreData;EvenMoreData1;200

记录1,字段2)

Data;moreData;EvenMoreData1;200

记录2,字段1)

Data;moreData;EvenMoreData2;500

记录2,字段1)

Data;moreData;EvenMoreData2;0

记录3,字段1)

Data;moreData;EvenMoreData3;0

记录3,字段2)

Data;moreData;EvenMoreData3;0

现在我已经到了这一步,我意识到我根本不需要设置FS,因为regexp我最终操作整个记录而不是单个字段,所以这实际上是我所需要的:< / p>

$ awk -v RS= -v ORS='\n\n' '/;0(\n|$)/' file
Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0

Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

只是在“\ n”所标记的任何行的末尾(例如,在每条记录的第1行的末尾)或在“由”标识的记录的末尾处查找正则表达式“; 0” $“(例如,在每条记录的第2行末尾,因此/; 0(\ n | $)/将在记录中的任何一行的末尾找到”; 0“。

希望有帮助,并为我在不需要时设置FS的混乱道歉,这是我第一次开始研究这个问题时的神器。

对于高尔夫球手:

$ awk '/;0(\n|$)/' RS= file
Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0
Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0

答案 3 :(得分:-1)

$ awk -F';' 'NR%3!=0{f=$NF;a=$0;getline;if(f==0||$NF==0)print a"\n"$0"\n"}' file
Data;moreData;EvenMoreData2;500
Data;moreData;EvenMoreData2;0

Data;moreData;EvenMoreData3;0
Data;moreData;EvenMoreData3;0