仅当此范围中包含另一个模式时,如何在两个模式之间打印一系列线条?

How to print a range of lines between two patterns only if another pattern is included in this range?

我正在 Linux 上处理文本文件。我希望仅当在这些行中找到另一个模式时才能够打印两个模式之间的所有行(包括找到模式的行)。

例如:

PatternStart
line1
line2
PatternInside
line3
line4
PatternEnd

PatternStart
line1
line2
line3
PatternEnd

我只想获取第一行,因为它包含 PatternInside。 现在,我所能做的就是用

提取边界图案之间的线条
awk '/PatternStart/,/PatternEnd/' file

但这会提取两行。

您可以使用

awk 'flag{
    buf = buf [=10=] ORS;
    if (/PatternEnd/ && buf ~ /PatternInside/)
       {printf "%s", buf; flag=0; buf=""}
}
/PatternStart/{buf = [=10=] ORS; flag=1}' file

此处,/PatternStart/{buf = [=12=]; flag=1}' 找到与 PatternStart 模式匹配的行,开始将输出值写入 buf,并设置标志。如果该标志为真,后续行将附加到 buf,并且一旦有一行 PatternEnd 匹配并且 PatternInsidebuf 中找到匹配项,则匹配被打印,buf 被清除并且标志被重置。

查看 online demo 产生

PatternStart
line1
line2
PatternInside
line3
line4
PatternEnd

这可能适合您 (GNU sed):

sed -n '/PatternStart/{:a;N;/PatternEnd/!ba;/PatternInside/p}' file

通过设置 -n 关闭隐式打印。

匹配 PatternStart,追加后续行直到 PatternEnd 匹配,然后检查集合中的字符串 PatternInside,如果是则打印集合。

使用保留的替代解决方案 space:

sed -n 'H;/PatternStart/h;/PatternEnd/{g;/PatternInside/p}' file

如果块之间有空行

$ awk -v RS= '/^PatternStart.*PatternInside.*PatternEnd$/' file

PatternStart
line1
line2
PatternInside
line3
line4
PatternEnd