![如何 grep 文件中的文本并显示包含该文本的段落?](https://linux22.com/image/45006/%E5%A6%82%E4%BD%95%20grep%20%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E6%96%87%E6%9C%AC%E5%B9%B6%E6%98%BE%E7%A4%BA%E5%8C%85%E5%90%AB%E8%AF%A5%E6%96%87%E6%9C%AC%E7%9A%84%E6%AE%B5%E8%90%BD%EF%BC%9F.png)
以下是文件中的文本:
Pseudo name=Apple
Code=42B
state=fault
Pseudo name=Prance
Code=43B
state=good
我需要 grep 查找“42B”并从上面的文本中获取输出,例如:
Pseudo name=Apple
Code=42B
state=fault
有谁知道如何使用grep
//来实现这awk
一点sed
?
答案1
和awk
awk -v RS='' '/42B/' file
RS=
将输入记录分隔符从换行符更改为空行。如果记录中的任何字段包含/42B/
打印该记录。
''
(空字符串)是一个神奇的值,用于表示空行根据 POSIX:
如果RS为空,则记录由由 a 加一个或多个空行组成的序列分隔
<newline>
,前导或尾随空行不应导致输入的开头或结尾处出现空记录,并且 a<newline>
应始终是字段分隔符,无论有什么价值FS是。
输出段落不会被分隔,因为输出分隔符仍然是单个换行符。为了确保输出段落之间有空行,请将输出记录分隔符设置为两个换行符:
awk -v RS='' -v ORS='\n\n' '/42B/' file
答案2
假设数据是结构化的,因此它始终是您想要的之前和之后的行,您可以使用 grep 的-A
(之后)和-B
(之前)开关来告诉它包含匹配之前的 1 行和匹配之后的 1 行:
$ grep -A 1 -B 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault
如果您希望搜索词前后有相同的数字行,您可以使用-C
(context) 开关:
$ grep -C 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault
如果您想在匹配多行时更加严格,可以使用该工具pcregrep
,匹配多行模式:
$ pcregrep -M 'Pseudo.*\n.*42B.*\nstate.*' sample.txt
Pseudo name=Apple
Code=42B
state=fault
上面的模式匹配如下:
-M
- 多行'Pseudo.*\n.*42B.*\nstate.*'
- 匹配一组字符串,其中第一个字符串以单词开头,"Pseudo"
后跟任何字符,直到行尾\n
,然后是任何字符,直到该字符串,"42B"
后跟任何字符,直到行的另一端 (\n
),最后是字符串"state"
后跟任何字符。
答案3
某些 Unix风格grep
的 Unix 版本有-p
“段落”标志。我知道AIX 确实如此。
grep -p 42B <myfile>
会完全按照你的要求去做。 YMMV 和 GNU grep 没有这个标志。
答案4
另一个 perl 解决方案,没有尾随空行:
perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
例子
% perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
Pseudo name=Apple
Code=42B
state=fault
% cat foo
Pseudo name=Apple
Code=42B
state=fault
Pseudo name=Prance
Code=43B
state=good