shell – 如何在两种模式之间选择行?

我有一个如下的文件,我想打印两个给定的模式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}在行中找到文本PAT1时设置标志.
> / PAT2 / {flag = 0}在行中找到文本PAT2时取消标志.
> flag是一个带有默认动作的模式,它是打印$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}’文件.

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

通过将标志置于最后,它触发在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

通过将标志置于一开始,它触发先前设置的动作,因此打印关闭模式,而不是初始化模式.

在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.在这一点上,它打印存储的内容并清空缓冲区.

相关文章
相关标签/搜索