48

使用 grep 我知道如何将上下文设置为固定数量的行。是否可以根据任意字符串条件显示上下文,例如将上下文设置为“直到下一个空白行”?

或者可能是其他一些工具组合?

基本上我有一个连续行的日志文件,用空白行分隔“事件”我想在日志文件中搜索一个字符串,但显示整个事件......

4

4 回答 4

49

听起来你需要sed

sed -n '/pattern/,/^$/p' file

默认情况下不打印 ( -n)。/pattern/对于与空行匹配的行/^$/,打印。

于 2012-11-23T18:44:25.627 回答
27

一个简单的解决方案是:

awk '/pattern/' RS= input-file

将 RS 设置为空字符串使 awk 将空行视为记录分隔符,而简单的规则/pattern/使 awk 打印任何与模式匹配的记录,可以是任何扩展的正则表达式。

于 2012-11-23T23:06:51.387 回答
9

这是一个(经过测试的)awk解决方案,为了便于阅读,分成多行:

awk '/pattern/ {do_print=1}
     do_print==1 {print}  
     NF==0 {do_print=0}' input_file

该脚本还将打印空白行,以便更容易在视觉上分离不同的匹配块。如果您不想要空行,请交换 2 行do_print==1 {print}NF==0 {do_print=0}

解释:

  • awk:调用该awk工具 - 它按顺序一次一行地评估输入。
  • '...'.: 用单引号括起来的所有内容都awk作为说明给出。在这种情况下,我们在每一行上执行引用的指令。
  • /pattern/ {do_print=1}:只要一行包含“ pattern”,打开do_print标志
  • do_print==1 {print}: 如果do_print标志设置为 on,则打印当前行。
  • NF==0 {do_print=0}: NF 代表字段数。awk默认情况下,用空格和制表符分隔每一行,以将一行分成多个字段。在这种情况下,一个空白行通常没有字段 - 所以我们在看到一行时关闭do_print标志以停止打印NF == 0
于 2012-11-23T18:53:44.930 回答
0

就我个人而言,我喜欢@William Pursell 的答案,因为之前的上下文通常很有用(例如,在查找ini文件中的内容时)。如果您实际上只想要 after 上下文,awk您可以这样做:

$ cat demo.ini 
[foo]
aaa = 1
bbb = 2
ccc = 3

[bar]
eee = 8
fff = 0
ggg = 1

[baz]
xxx = 1
yyy = 0
zzz = 2
$ awk '/bar/,/^$/' demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1

$ awk '/fff/,/^$/' demo.ini 
fff = 0
ggg = 1

$

RS=版本比较:

$ awk '/bar/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
$ awk '/fff/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
于 2018-11-12T23:54:03.857 回答