使用 awk 从文件中提取非常特定的部分

使用 awk 从文件中提取非常特定的部分

我正在尝试编写一个脚本(实际上是一个单行脚本)来提取调试日志的重要部分,以便人们可以轻松地将其发送给我,而不是把我拖到电话会议上或必须收集整个文件。我可以告诉他们在 less 或 vi 中做什么来获取信息,但如果可能的话,我希望它作为命令。

less

$ less filename
G
?Server\ version
/SEVERE
[read line including first match for SEVERE from this point, stop reading when get to next instance of SEVERE]

我一直在尝试编写一个awk命令来完成此任务,但进展并不顺利。

这是我所得到的最接近的结果,但不起作用:

awk '{if (/Server version/) {chunk=""} else {chunk=chunk $0 RS}} END {printf "%s", chunk}'  filename | awk '/SEVERE/,/SEVERE/'

awk似乎不喜欢在我想在最后打印的部分的开头和结尾使用相同的模式。

我愿意使用其他工具,但对于我的用例,我需要使用 RHEL7 上默认提供的实用程序。

如果这些信息有帮助,我正在查看 apache tomcat 调试日志。

答案1

SEVERE如果我理解正确的话,您想输出最后一次出现 后第一次出现和下一次出现之间的行Server version

输入文件示例:

Server version
SEVERE
ignore
SEVERE
Server version
ignore
SEVERE
important
stuff
SEVERE 
ignore
SEVERE
awk '
  /Server version/{ chunk="" }
  /SEVERE/{ logme=(chunk=="") }
  logme{ chunk=chunk $0 RS }
  END{ printf "%s", chunk }
' file

输出:

SEVERE
important
stuff

答案2

多行大纲:使用 grep 打印行号,提取它们并使用 awk

grep -n SEVERE filename | head -n 2 | cut -d ':' -f1

这将输出包含“SEVERE”的前 2 个行号 [a, b],并且 awk 可以轻松打印 SEVERE 和中间行...

awk 'NR>=a && NR<=b {print $0;}' filename

这可以很容易地编写脚本 - 但它需要两次通过日志文件。

相关内容