如何在包含或不包含(在 sed、AWK 或 Perl 中)的两个模式之间打印线? [英] How to print lines between two patterns, inclusive or exclusive (in sed, AWK or Perl)?

查看:20
本文介绍了如何在包含或不包含(在 sed、AWK 或 Perl 中)的两个模式之间打印线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个如下所示的文件,我想打印两个给定模式 PAT1PAT2 之间的行.

I have a file like the following and I would like to print the lines between two given patterns PAT1 and PAT2.

1
2
PAT1
3    - first block
4
PAT2
5
6
PAT1
7    - second block
PAT2
8
9
PAT1
10    - third block

我已经阅读了如何在两个标记模式之间选择线,这可能会用 awk/sed 多次出现,但我是很想看到所有可能的组合,包括或不包括模式.

I have read How to select lines between two marker patterns which may occur multiple times with awk/sed but I am curious to see all the possible combinations of this, either including or excluding the pattern.

如何打印两个图案之间的所有线条?

How can I print all lines between two patterns?

推荐答案

打印 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 时设置 flag.
  • /PAT2/{flag=0} 在一行中找到文本 PAT2 时取消设置 flag.
  • flag 是一个带有默认动作的模式,即 print $0:如果 flag 等于 1,则打印该行.这样,它将打印从 PAT1 出现到下一个 PAT2 出现的所有行.这还将打印从 PAT1 的最后一个匹配到文件末尾的行.
  • /PAT1/ matches lines having this text, as well as /PAT2/ does.
  • /PAT1/{flag=1} sets the flag when the text PAT1 is found in a line.
  • /PAT2/{flag=0} unsets the flag when the text PAT2 is found in a line.
  • flag is a pattern with the default action, which is to print $0: if flag is equal 1 the line is printed. This way, it will print all those lines occurring from the time PAT1 occurs and up to the next PAT2 is seen. This will also print the lines from the last match of PAT1 up to the end of the file.
$ awk '/PAT1/{flag=1; next} /PAT2/{flag=0} flag' file
3    - first block
4
7    - second block
10    - third block

这使用 next 跳过包含 PAT1 的行以避免打印.

This uses next to skip the line that contains PAT1 in order to avoid this being printed.

next 的调用可以通过重新排列块来删除: awk '/PAT2/{flag=0} flag;/PAT1/{flag=1}' 文件.

This call to next can be dropped by reshuffling the blocks: awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file.

$ 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 上打印.

By placing flag at the very end, it triggers the action that was set on either PAT1 or PAT2: to print on PAT1, not to print on PAT2.

$ awk 'flag; /PAT1/{flag=1} /PAT2/{flag=0}' file
3    - first block
4
PAT2
7    - second block
PAT2
10    - third block

通过在最开始放置flag,它会触发之前设置的动作,因此打印结束模式而不是开始模式.

By placing flag at the very beginning, it triggers the action that was set previously and hence print the closing pattern but not the starting one.

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

This keeps all the selected lines in a buffer that gets populated from the moment PAT1 is found. Then, it keeps being filled with the following lines until PAT2 is found. In that point, it prints the stored content and empties the buffer.

这篇关于如何在包含或不包含(在 sed、AWK 或 Perl 中)的两个模式之间打印线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆