我有一个类似以下的文件,我想在两个给定模式PAT1PAT2之间打印行。

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/

    10-11 11:14