如何在匹配之前和之后打印行直到特定匹配(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' text
或 sed -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。这假设 AAA
和 FFF
是配对的,如果不使用:
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
编辑:
对于行首的AAA
、CCC
和FFF
,使用:
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
我有一个很长的数据,它是按块构建的。
在下面的示例中,让我们看看它们以 (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' text
或 sed -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。这假设 AAA
和 FFF
是配对的,如果不使用:
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
编辑:
对于行首的AAA
、CCC
和FFF
,使用:
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