Regex 查找特定图案并使用awk或sed打印完整的文本块

Regex 查找特定图案并使用awk或sed打印完整的文本块,regex,sed,awk,Regex,Sed,Awk,如何在文本块中找到一个特定的数字,并打印以关键字“BEGIN”开头,以“END”结尾的完整的文本块?基本上,我的文件是这样的: BEGIN A: abc B: 12345 C: def END BEGIN A: xyz B: 56789 C: abc END BEGIN A: ghi B: 56712 C: pqr END [...] 如果我正在查找“^B:567”,我希望获得以下输出: BEGIN A: xyz B: 56789 C: abc END BEGIN A: ghi B:

如何在文本块中找到一个特定的数字,并打印以关键字
“BEGIN”
开头,以
“END”
结尾的完整的文本块?基本上,我的文件是这样的:

BEGIN
A: abc
B: 12345
C: def
END

BEGIN
A: xyz
B: 56789
C: abc
END

BEGIN
A: ghi
B: 56712
C: pqr
END

[...]
如果我正在查找
“^B:567”
,我希望获得以下输出:

BEGIN
A: xyz
B: 56789
C: abc
END

BEGIN
A: ghi
B: 56712
C: pqr
END
我可以在这里使用grep(
grep-E-B2-A2“^B:567”文件
),但我想得到一个更通用的解决方案。我想awk或sed可能能做到这一点


谢谢!:)

您可以取消定义
RS
以在空行中拆分记录,并检查字符串在整个块中是否匹配:

awk 'BEGIN { RS = "" } /\nB:[[:space:]]+567/ { print $0 ORS }' infile
它产生:

BEGIN
A: xyz
B: 56789
C: abc
END 

BEGIN
A: ghi
B: 56712
C: pqr
END
此awk应在以下情况下工作:

awk -v s='B: 567' '$0~s' RS= file
BEGIN
A: xyz
B: 56789
C: abc
END
BEGIN
A: ghi
B: 56712
C: pqr
END

有点长,但是RS的把戏已经发布了:-)

输出:

$ awk -f s.awk input
BEGIN
A: xyz
B: 56789
C: abc
END
BEGIN
A: ghi
B: 56712
C: pqr
END
这可能适用于您(GNU-sed):

或者这个:

sed -n '/^BEGIN/!b;:a;$!{N;/\nEND/!ba};/\nB: 567/p' file

请注意
\n
之前的
B
以确保它出现在一行的开头。这取代了您最初使用的
^
字符串开头,因为现在每一行都不是它自己的字符串。你需要将上面的OR设置为在记录之间重新插入空白行。

@ EdMORTON:任何搜索字符串都可以在这个命令中传递。但是,在这个例子中使用OP需要的字符串不会有坏处。你不需要<代码> $ 0~<代码> < 0代码】:[[:空间:] + 567 / < /代码>,你应该去掉<代码>逗号0美元中的逗号。ORS,因此不需要在输出中的每个
结束后添加空格字符。如果
B:567
显示为
A:…
行中的文本,您确实需要锚定
B
。@EdMorton:谢谢。修正。你真的应该让它成为
\nB
而不仅仅是
B
。如果567出现在任何一行的任何地方,就会产生错误的匹配,并且可以重新排序输出中的文本,以便在开始之前结束,或者任何其他排列,这是
for(a中的i)
的礼貌。
sed -n '/^BEGIN/{x;d};H;/^END/{x;s/^B: 567/&/mp}' file
sed -n '/^BEGIN/!b;:a;$!{N;/\nEND/!ba};/\nB: 567/p' file
perl -lne 'if(/56789/){$f=1}
           push @a,$_;
           if(/END/){
              if($f){print join "\n",@a}
           undef @a;$f=0}' your_file
$ awk -v RS= -v ORS='\n\n' '/\nB: 567/' file
BEGIN
A: xyz
B: 56789
C: abc
END

BEGIN
A: ghi
B: 56712
C: pqr
END