我有一个类似于下面的文件,我想打印两种给定模式PAT1和PAT2之间的线条。
1
2
PAT1
3 - first block
4
PAT2
5
6
PAT1
7 - second block
PAT2
8
9
PAT1
10 - third block我读过如何在使用awk/sed时多次出现的两个标记模式之间选择行?,但我很好奇地看到所有可能的组合,包括或排除模式。
如何打印两种模式之间的所有线条?
发布于 2016-08-16 10:40:13
PAT1和PAT2之间的打印线
$ awk '/PAT1/,/PAT2/' file
PAT1
3 - first block
4
PAT2
PAT1
7 - second block
PAT2
PAT1
10 - third block或者,使用变量:
awk '/PAT1/{flag=1} flag; /PAT2/{flag=0}' file这是怎么回事?
/PAT1/与具有此文本的行匹配,也与/PAT2/匹配。/PAT1/{flag=1}在一行中找到文本PAT1时设置PAT1。/PAT2/{flag=0}时,flag会取消设置。flag是一个默认操作的模式,即print $0:如果flag为1,则打印行。通过这种方式,它将打印从PAT1发生到看到下一个PAT2的所有行。这还将打印从最后一次PAT1匹配到文件末尾的行。PAT1和PAT2之间的打印线--不包括PAT1和PAT2
$ awk '/PAT1/{flag=1; next} /PAT2/{flag=0} flag' file
3 - first block
4
7 - second block
10 - third block这使用next跳过包含PAT1的行,以避免打印。
这个对next的调用可以通过重新设置块:awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file来删除。
PAT1和PAT2之间的打印行--包括PAT1
$ awk '/PAT1/{flag=1} /PAT2/{flag=0} flag' file
PAT1
3 - first block
4
PAT1
7 - second block
PAT1
10 - third block通过将flag放在最末尾,它将触发在PAT1或PAT2上设置的操作:在PAT1上打印,而不是在PAT2上打印。
PAT1和PAT2之间的打印行--包括PAT2
$ awk 'flag; /PAT1/{flag=1} /PAT2/{flag=0}' file
3 - first block
4
PAT2
7 - second block
PAT2
10 - third block通过将flag放在最开始的位置,它将触发先前设置的操作,从而打印结束模式,而不是开始模式。
PAT1和PAT2之间的打印行--如果没有发生其他PAT2,则不包括从最后一个PAT1到文件末尾的行
这是基于埃德·莫顿的一个解决方案的。
awk 'flag{
if (/PAT2/)
{printf "%s", buf; flag=0; buf=""}
else
buf = buf $0 ORS
}
/PAT1/ {flag=1}' file作为一条单线:
$ awk 'flag{ if (/PAT2/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /PAT1/{flag=1}' file
3 - first block
4
7 - second block
# note the lack of third block, since no other PAT2 happens after it这会将所有选定的行保存在一个缓冲区中,从找到PAT1时开始填充。然后,它将一直填充以下行,直到找到PAT2为止。在这一点上,它打印存储的内容并清空缓冲区。
发布于 2016-08-16 13:10:08
使用grep与PCRE (在可用的情况下)使用打印标记和标记之间的行
$ grep -Pzo "(?s)(PAT1(.*?)(PAT2|\Z))" file
PAT1
3 - first block
4
PAT2
PAT1
7 - second block
PAT2
PAT1
10 - third block-P perl-regexp,PCRE.不是所有的grep变体-z将输入视为一组行,每一行以零字节结尾,而不是以换行符结尾。-o只打印匹配(?s) DotAll .点也能找到新行。(.*?)非贪婪查找\Z只匹配字符串的末尾,或尾的换行符之前。标记之间的打印行(不包括末端标记)
$ grep -Pzo "(?s)(PAT1(.*?)(?=(\nPAT2|\Z)))" file
PAT1
3 - first block
4
PAT1
7 - second block
PAT1
10 - third block(.*?)(?=(\nPAT2|\Z))非贪婪查找\nPAT2和\Z不包括标记的标记之间的打印行
$ grep -Pzo "(?s)((?<=PAT1\n)(.*?)(?=(\nPAT2|\Z)))" file
3 - first block
4
7 - second block
10 - third block(?<=PAT1\n)对PAT1\n的正向跟踪标记之间的打印行不包括起始标记
$ grep -Pzo "(?s)((?<=PAT1\n)(.*?)(PAT2|\Z))" file
3 - first block
4
PAT2
7 - second block
PAT2
10 - third block发布于 2019-04-20 12:16:56
为了完整起见,这里有一个Perl解决方案:
PAT1和PAT2之间的打印行-包括PAT1和PAT2
perl -ne '/PAT1/../PAT2/ and print' FILE或者:
perl -ne 'print if /PAT1/../PAT2/' FILEPAT1和PAT2之间的打印行-排除PAT1和PAT2
perl -ne '/PAT1/../PAT2/ and !/PAT1/ and !/PAT2/ and print' FILE或者:
perl -ne 'if (/PAT1/../PAT2/) {print unless /PAT1/ or /PAT2/}' FILE PAT1和PAT2之间的打印行-仅排除PAT1
perl -ne '/PAT1/../PAT2/ and !/PAT1/ and print' FILEPAT1和PAT2之间的打印行-仅排除PAT2
perl -ne '/PAT1/../PAT2/ and !/PAT2/ and print' FILE另请参阅:
perldoc perlop语法的更多信息,请参见/PAT1/../PAT2/中的Range运算符部分:距离算子 ...In标量上下文,“.”返回布尔值。操作符是双稳态的,就像触发器一样,并模拟sed、awk和各种编辑器的行范围(逗号)操作符。
-n选项,请参见perldoc perlrun,它使Perl的行为类似于sed -n。https://stackoverflow.com/questions/38972736
复制相似问题