在先前不同的匹配模式之前和之后搜索下一个出现的模式,并将其间的所有内容提取到不同的文件中

在先前不同的匹配模式之前和之后搜索下一个出现的模式,并将其间的所有内容提取到不同的文件中

我的服务器上有一个巨大的日志文件(数十GB)。它太大,无法在合理的时间内下载。然而,我实际上只对相对较小的线条子集感兴趣。日志文件具有类似 xml 的结构。有很多<log>...</log>条目,其中之一有我正在寻找的特定模式,可以说"Failure"(当grep"Failure"只有 1 个匹配项时):

<log>...</log>
<log>...</log>

....

<log>  (*1*)
      ...
      ... "Failure" ...
      ... 
</log> (*2*)

....

<log>...</log>
<log>...</log>

我的想法是分别搜索包含 的行的前一个和下一个出现位置<log> (*1*)以及之前和之后的位置。之后我想将这些行复制到一个单独的文件中,然后我可以轻松下载该文件。</log> (*2*)"Failure"

伪代码总结:

failure_line = find pattern "Failure" in log file
start_line = find immediate previous occurrence of <log> before the line failure_line
finish_line = find immediate next occurrence of </log> after the line failure_line
copy all lines from start_line until finish_line to a new file

这可以通过脚本来实现bash而不需要很大的开销吗?

答案1

请注意,标准文本处理工具(如sedperl或 )awk并不用于 XML 解析。如果你可以依赖一些东西,比如<log>...</log>一行中不超过一对,你可以这样做sed

sed '/<log>.*<\/log>/{/Failure/p;d;};/<log>/,/<\/log>/H;/<log>/h;/<\/log>/!d;x;/Failure/!d' your.log
  • '/.*</log>/' 将行与完整的标记匹配。这些需要单独处理:/Failure/p如果它们包含 则打印它们Failured停止进一步处理。
  • 现在/<log>/,/<\/log>/选择开头<log>和结尾之间的行</log>并将它们附加到保留空间( 的剪贴板sedH
  • /<log>/hlog初始化任何新序列的保留空间
  • /<\/log>/!d停止处理所有行,但那些有关闭的行</log>
  • 因此,仅在关闭日志时执行以下操作:x交换保持空间和模式空间,因此我们拥有自上一行以来收集的模式空间中的所有内容<log>d如果不包含则删除它Failure,否则默认情况下会在脚本末尾打印

相关内容