如何在匹配之前和之后打印行直到特定匹配(3 种匹配模式)

How to print lines before and after a match until a specific match (3 matching patterns)

我有一个很长的数据,它是按块构建的。

在下面的示例中,让我们看看它们以 (AAA) 开头并以 (FFF) 结尾,它们之间可能有很多行信息

我想提取特定块,前提是模式 (CCC) 在这些块内。

例如:

cat text
AAA1
BBB
FFF1
AAA2
BBB
CCC2
DDD
EEE
FFF2
AAA3
BBB
FFF3
AAA4
BBB
CCC4
DDD
EEE
FFF4

输出应该是:

AAA2
BBB
CCC2
DDD
EEE
FFF2
AAA4
BBB
CCC4
DDD
EEE
FFF4

我考虑过使用 sed,但没有真正起作用: 如果使用这只会让我从 CCC 到下一个 AAA/FFF: sed -n -e '/CCC/,/AAA/ p' textsed -n -e '/CCC/,/AAA/ p' text

CCC2
DDD
EEE
FFF2
AAA3
CCC4
DDD
EEE
FFF4

如果我这样使用它:sed -n -e '/AAA/,/FFF/ p' text我将捕获 AAA 和 FFF 之间没有 CCC 的模式。

您可以将输入视为数据块,将 AAA.* 作为开始标记,将 FFF.* 作为结束标记。现在将每个块收集到 hold-space 并在结束标记处检查块是否包含所需的模式。

例如,这是执行此操作的 GNU sed 版本:

parse.sed

# Start-tag -> start a new block in hold-space
/^AAA/ { h; b; }

# Save input
H

# End-tag AND block contains CCC -> print
/^FFF/ { x; /\nCCC/ p; }

运行 像这样,例如:

sed -nf parse.sed | sed '/^FFF/G'

或作为单行:

sed -n '/^AAA/{h;b};H;/^FFF/{x;/\nCCC/p}' | sed '/^FFF/G'

输出:

AAA2
BBB
CCC2
DDD
EEE
FFF2

AAA4
BBB
CCC4
DDD
EEE
FFF4

一个更便携的 sed 脚本如下所示:

# Start-tag -> start a new block in hold-space
/^AAA/ { 
  h
  b
}

# Save input
H

# End-tag AND block contains CCC -> print
/^FFF/ { 
  x
  /\nCCC/p
}

这可能适合您 (GNU sed):

sed -n '/AAA/{:a;N;/FFF/!ba;/CCC/p}' file

关闭隐式打印-n,因为这是一个过滤操作。

匹配包含 AAA 的行并追加更多行直到包含 FFF.

的行

如果集合包含字符串 CCC,打印它。

重复。

N.B。这假设 AAAFFF 是配对的,如果不使用:

sed -n '/AAA/{:a;N;/\n.*AAA/s/.*\n//;/FFF/!ba;/CCC/p}' file

选择:

sed -n 'H;/AAA/h;/FFF/{g;/AAA.*CCC/p;z;h}' file

编辑:

对于行首的AAACCCFFF,使用:

sed -n '/^AAA/{:a;N;/^FFF/M!ba;/^CCC/Mp}' file

sed -n '/^AAA/{:a;N;/\nAAA/s/.*\n//;/\nFFF/!ba;/\nCCC/p}' file

sed -n 'H;/^AAA/h;/^FFF/{g;/AAA.*\nCCC/p;z;h}' file

在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ awk '/^AAA/{a=1; buf=""} /^CCC/{c=1} {buf=buf [=10=] ORS} /^FFF/{if (a && c) printf "%s", buf; a=c=0}' text
AAA2
BBB
CCC2
DDD
EEE
FFF2
AAA4
BBB
CCC4
DDD
EEE
FFF4

awk 变体

awk '/^AAA/{f=1} f{i=i [=10=] ORS} /^FFF/{if(i~/\nCCC/){printf "%s", i} i=f=""}' input