我有一个像下面这样的文件,我想打印两个给定模式之间的线 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但我很想看到所有可能的组合,无论是否打印图案 .
如何选择两种模式之间的线?
6 回答
在PAT1和PAT2之间打印行
或者,使用变量:
这是如何运作的?
/PAT1/
匹配具有此文本的行,以及/PAT2/
./PAT1/{flag=1}
在行中找到文本PAT1
时设置flag
./PAT2/{flag=0}
在行中找到文本PAT2
时取消设置flag
.flag
是具有默认操作的模式,即print $0
:如果flag
等于1,则打印该行 . 这样,它将打印从PAT1
发生的所有那些行,直到下一个PAT2
被看到 . 这也将打印从PAT1
的最后一个匹配到文件末尾的行 .在PAT1和PAT2之间打印行 - 不包括PAT1和PAT2
这使用
next
跳过包含PAT1
的行,以避免打印 .可以通过重新组合块来删除对
next
的调用:awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file
.在PAT1和PAT2之间打印行 - 包括PAT1
通过在最后放置
flag
,它会触发在PAT1或PAT2上设置的操作:在PAT1上打印,而不是在PAT2上打印 .在PAT1和PAT2之间打印行 - 包括PAT2
通过在最开始放置
flag
,它会触发先前设置的操作,从而打印关闭模式但不打印开始模式 .在PAT1和PAT2之间打印行 - 如果没有其他PAT2发生,则排除从最后一个PAT1到文件末尾的行
这基于a solution by Ed Morton .
作为单线:
这会将所有选定的行保留在从找到PAT1的那一刻起填充的缓冲区中 . 然后,它继续填充以下行,直到找到PAT2 . 在这一点上,它打印存储的内容并清空缓冲区 .
经典
sed
解决方案怎么样?在PAT1和PAT2之间打印行
甚至(谢谢Sundeep):
以上不包括范围边界 .
在PAT1和PAT2之间打印行 - 包括PAT1和PAT2
以下将包括范围边界,这甚至更简单:
在PAT1和PAT2之间打印行 - 包括PAT1
以下仅包括范围开始:
在PAT1和PAT2之间打印行 - 包括PAT2
以下仅包括范围结束:
使用
grep
与PCRE(如果可用)到 print markers and lines between markers :-P
perl-regexp,PCRE . 并非所有grep
变体-z
将输入视为一组行,每行以零字节而不是换行符结尾-o
仅打印匹配(?s)
DotAll,即 . dot也找到换行符(.*?)
不经常发现\Z
仅在字符串结尾处或在结尾处的换行符之前匹配Print lines between markers excluding end marker :
(.*?)(?=(\nPAT2|\Z))
nongreedy查找\nPAT2
和\Z
的预测Print lines between markers excluding markers :
(?<=PAT1\n)
PAT1\n
正向后视Print lines between markers excluding start marker :
这是另一种方法
Include both patterns (default)
Mask both patterns
Mask start pattern
Mask end pattern
您可以使用
sed
通过使用-n
抑制模式空间的正常打印来执行您想要的操作 . 例如,要在结果中包含模式,您可以执行以下操作:要排除模式并只打印它们之间的内容:
这打破了
sed -n '/PAT1/,/PAT2/
- 找到PAT1
和PAT2
之间的范围并禁止打印;/PAT1/{n};
- 如果匹配PAT1
移至n
(下一行)行;/PAT2/{d};
- 如果匹配PAT2
删除行;p
- 打印/PAT1/,/PAT2/
内所有未被跳过或删除的行 .或者:
这将删除除START和END之间和之外的所有行,然后
//d
删除START和END行,因为//
会导致sed使用以前的模式 .