为了账号安全,请及时绑定邮箱和手机立即绑定

如何在两种模式之间打印行,包括还是独占(在sed、AWK或Perl中)?

如何在两种模式之间打印行,包括还是独占(在sed、AWK或Perl中)?

胡子哥哥 2019-06-03 16:13:38
如何在两种模式之间打印行,包括还是独占(在sed、AWK或Perl中)?我有一个类似于下面的文件,我想打印两个给定模式之间的线条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时多次出现的两个标记模式之间选择行?但我很好奇地看到所有可能的组合,包括或排除模式。如何打印两种模式之间的所有线条?
查看完整描述

3 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

PAT1和PAT 2之间的打印线

$ awk '/PAT1/,/PAT2/' file
PAT13    - first block4PAT2
PAT17    - second block
PAT2
PAT110    - 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和PAT 2之间的打印线-不包括PAT 1和PAT 2

$ awk '/PAT1/{flag=1; next} /PAT2/{flag=0} flag' file3    - first block47    - second block10    - third block

这个用next跳过包含PAT1为了避免被打印出来。

这个电话next可以通过重新设置块来丢弃:awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file.

PAT1和PAT 2之间的打印线-包括PAT1

$ awk '/PAT1/{flag=1} /PAT2/{flag=0} flag' file
PAT13    - first block4PAT17    - second block
PAT110    - third block

通过放置flag最后,它触发在PAT1或PAT 2上设置的操作:在PAT 1上打印,而不是在PAT 2上打印。

PAT1和PAT 2之间的打印线-包括PAT 2

$ awk 'flag; /PAT1/{flag=1} /PAT2/{flag=0}' file3    - first block4PAT27    - second block
PAT210    - third block

通过放置flag在开始时,它会触发先前设置的操作,从而打印结束模式,而不是开始模式。

PAT1和PAT2之间的打印行-如果没有发生其他pat 2,则不包括从最后一个pat 1到文件末尾的行。

这是基于埃德·莫顿的一个解决方案.

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}' file3    - first block47    
- second block# note the lack of third block, since no other PAT2 happens after it

这会将所有选定的行保存在一个缓冲区中,该缓冲区从找到PAT 1时开始填充。然后,它将一直填充以下行,直到找到PAT 2为止。在这一点上,它打印存储的内容并清空缓冲区。


查看完整回答
反对 回复 2019-06-03
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

那经典呢?sed解决办法?

pat 1和pat 2之间的打印线-包括pat 1和pat 2。

sed -n '/PAT1/,/PAT2/p' FILE

PAT1和PAT 2之间的打印线-排除PAT1和PAT 2

GNUsed

sed -n '/PAT1/,/PAT2/{/PAT1/!{/PAT2/!p}}' FILE

任何sed1

sed -n '/PAT1/,/PAT2/{/PAT1/!{/PAT2/!p;};}' FILE

甚至(谢谢)孙迪普):

GNUsed

sed -n '/PAT1/,/PAT2/{//!p}' FILE

任何sed

sed -n '/PAT1/,/PAT2/{//!p;}' FILE

PAT1和PAT 2之间的打印线-包括PAT 1,但不包括PAT 2。

以下只是范围的开始:

GNUsed

sed -n '/PAT1/,/PAT2/{/PAT2/!p}' FILE

任何sed

sed -n '/PAT1/,/PAT2/{/PAT2/!p;}' FILE

在pat 1和pat 2之间的打印线-包括pat 2,但不包括pat 1。

以下内容仅包括范围结束:

GNUsed

sed -n '/PAT1/,/PAT2/{/PAT1/!p}' FILE

任何sed

sed -n '/PAT1/,/PAT2/{/PAT1/!p;}' FILE

1关于BSD/MacOSXsed的注意事项

这里有这样的命令:

sed -n '/PAT1/,/PAT2/{/PAT1/!{/PAT2/!p}}' FILE

会发出错误:

▶ sed -n '/PAT1/,/PAT2/{/PAT1/!{/PAT2/!p}}' FILE
sed: 1: "/PAT1/,/PAT2/{/PAT1/!{/ ...": extra characters at the end of p command

由于这个原因,这个答案已经被编辑,包括BSD和GNU版本的一行。


查看完整回答
反对 回复 2019-06-03
?
萧十郎

TA贡献1815条经验 获得超12个赞

使用grep与PCRE(如有)打印标记和标记之间的线条:

$ grep -Pzo "(?s)(PAT1(.*?)(PAT2|\Z))" file
PAT13    - first block4PAT2
PAT17    - second block
PAT2
PAT110    - third block
  • -P

    perl-regexp,PCRE.一点也不

    grep

    变体
  • -z

    将输入视为一组行,每一行以零字节结尾,而不是换行符。
  • -o

    只打印匹配
  • (?s)

    都是.点也能找到新行。
  • (.*?)

    非贪婪发现
  • \Z

    只匹配字符串的末尾,或换行符后面的换行符。

标记之间的打印行(不包括结束标记):

$ grep -Pzo "(?s)(PAT1(.*?)(?=(\nPAT2|\Z)))" file
PAT13    - first block4PAT17    - second block
PAT110    - third block
  • (.*?)(?=(\nPAT2|\Z))

    非贪婪查找

    \nPAT2

    \Z

除标记外的标记之间的打印行:

$ grep -Pzo "(?s)((?<=PAT1\n)(.*?)(?=(\nPAT2|\Z)))" file3    - first block47    - second block10    - third block
  • (?<=PAT1\n)

    积极寻找

    PAT1\n

标记之间的打印行(不包括开始标记):

$ grep -Pzo "(?s)((?<=PAT1\n)(.*?)(PAT2|\Z))" file3    - first block4PAT27    - second block
PAT210    - third block


查看完整回答
反对 回复 2019-06-03
  • 3 回答
  • 0 关注
  • 607 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信