我有一个类似以下的文件,我想在两个给定模式PAT1
和PAT2
之间打印行。
1
2
PAT1
3 - first block
4
PAT2
5
6
PAT1
7 - second block
PAT2
8
9
PAT1
10 - third block
我已经读过How to select lines between two marker patterns which may occur multiple times with awk/sed,但是很好奇所有可能的组合,包括或不包括模式。
如何打印两个图案之间的所有行?
最佳答案
在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}
时,flag
设置PAT1
。 /PAT2/{flag=0}
时,flag
会取消设置PAT2
。 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
,它会触发先前设置的 Action ,因此打印关闭模式,但不打印开始模式。在PAT1和PAT2之间打印行-如果没有其他PAT2,则不包括从最后一个PAT1到文件末尾的行
这基于a solution by Ed Morton。
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。此时,它会打印存储的内容并清空缓冲区。
关于shell - 如何在两种模式(包括sed,AWK或Perl)之间打印行?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38972736/