猿问

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

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

我有一个类似于下面的文件,我想打印两个给定模式之间的线条PAT1PAT2.

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

我读过如何在使用awk/sed时多次出现的两个标记模式之间选择行?但我很好奇地看到所有可能的组合,包括或排除模式。

如何打印两种模式之间的所有线条?


胡子哥哥
浏览 608回答 3
3回答

MYYA

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

慕码人2483693

那经典呢?sed解决办法?pat 1和pat 2之间的打印线-包括pat 1和pat 2。sed -n '/PAT1/,/PAT2/p' FILEPAT1和PAT 2之间的打印线-排除PAT1和PAT 2GNUsedsed -n '/PAT1/,/PAT2/{/PAT1/!{/PAT2/!p}}' FILE任何sed1sed -n '/PAT1/,/PAT2/{/PAT1/!{/PAT2/!p;};}' FILE甚至(谢谢)孙迪普):GNUsedsed -n '/PAT1/,/PAT2/{//!p}' FILE任何sedsed -n '/PAT1/,/PAT2/{//!p;}' FILEPAT1和PAT 2之间的打印线-包括PAT 1,但不包括PAT 2。以下只是范围的开始:GNUsedsed -n '/PAT1/,/PAT2/{/PAT2/!p}' FILE任何sedsed -n '/PAT1/,/PAT2/{/PAT2/!p;}' FILE在pat 1和pat 2之间的打印线-包括pat 2,但不包括pat 1。以下内容仅包括范围结束:GNUsedsed -n '/PAT1/,/PAT2/{/PAT1/!p}' FILE任何sedsed -n '/PAT1/,/PAT2/{/PAT1/!p;}' FILE1关于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版本的一行。

萧十郎

使用grep与PCRE(如有)打印标记和标记之间的线条:$&nbsp;grep&nbsp;-Pzo&nbsp;"(?s)(PAT1(.*?)(PAT2|\Z))"&nbsp;file PAT13&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;first&nbsp;block4PAT2 PAT17&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;second&nbsp;block PAT2 PAT110&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;third&nbsp;block-Pperl-regexp,PCRE.一点也不grep变体-z将输入视为一组行,每一行以零字节结尾,而不是换行符。-o只打印匹配(?s)都是.点也能找到新行。(.*?)非贪婪发现\Z只匹配字符串的末尾,或换行符后面的换行符。标记之间的打印行(不包括结束标记):$&nbsp;grep&nbsp;-Pzo&nbsp;"(?s)(PAT1(.*?)(?=(\nPAT2|\Z)))"&nbsp;file PAT13&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;first&nbsp;block4PAT17&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;second&nbsp;block PAT110&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;third&nbsp;block(.*?)(?=(\nPAT2|\Z))非贪婪查找\nPAT2和\Z除标记外的标记之间的打印行:$&nbsp;grep&nbsp;-Pzo&nbsp;"(?s)((?<=PAT1\n)(.*?)(?=(\nPAT2|\Z)))"&nbsp;file3&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;first&nbsp;block47&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;second&nbsp;block10&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;third&nbsp;block(?<=PAT1\n)积极寻找PAT1\n标记之间的打印行(不包括开始标记):$&nbsp;grep&nbsp;-Pzo&nbsp;"(?s)((?<=PAT1\n)(.*?)(PAT2|\Z))"&nbsp;file3&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;first&nbsp;block4PAT27&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;second&nbsp;block PAT210&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;third&nbsp;block
随时随地看视频慕课网APP
我要回答