grep 与“从这个到那个”触发器语义?

kdb*_*kdb 1 perl awk grep

grep允许通过使用看到匹配的上下文-A-B-C选项,例如

grep -B 3 -A 10 "WARNING" MyApp.log 
Run Code Online (Sandbox Code Playgroud)

perl one-liners 允许轻松提取文本,即在开始和结束行之间,每个文本匹配不同的正则表达式,使用形式中的双稳态翻转运算符

perl -ne '(/^WARNING/../^$/) && print' MyApp.log
Run Code Online (Sandbox Code Playgroud)

但是除了编写更复杂的脚本之外,没有明显的方法来包含上下文行 - 绝对不是在命令行上快速使用的临时解决方案。

是否有一些功能grep/ perl,我很想念,或者一些第三方工具,允许组合这两个触发器的语义和情境线?

Sha*_*awn 5

如果我理解你的问题是正确的,你想在匹配正则表达式的行之前打印出从 N 行开始的块,然后打印到下一个空行和它之后的 M 行?

对于 good old 来说,这实际上很简单ed

$ cat foo.log
line 1
line 2
line 3
line 4
WARNING LINE
line 5
line 6

line 7
line 8
line 9
line 10
line 11
WARNING LINE
line 12

line 13
line 14
$ printf '%s\n' 'g/^WARNING/-3,/^$/+1p' | ed -s foo.log
line 2
line 3
line 4
WARNING LINE
line 5
line 6

line 7
line 9
line 10
line 11
WARNING LINE
line 12

line 13
Run Code Online (Sandbox Code Playgroud)

如您所见,此特定调用打印出每个 WARNING 之前的 3 行,直到下一个空行之后的行。但是,对于非常大的文件,这不是一个好的解决方案,因为ed加载整个文件。如果是这种情况,您需要一些可以保持滚动窗口的行。这是一个perl跟踪上下文的示例:

perl -ne 'push @lines, $_;
          if (/^WARNING/../^$/) { $in_warn = 1 }
          shift @lines if !$in_warn && @lines > 3;
          if ($in_warn && /^$/) { $end_line = $. + 1 }
          if ($end_line == $.) { print @lines; @lines=(); $in_warn = 0 }' foo.log
Run Code Online (Sandbox Code Playgroud)