bash - 从文件中的特定行以相反的顺序 Grep 文件

标签 bash perl awk sed grep

我有这种日志

2019-11-14T20:03:48.917Z  INFO Thread1 Audit ... Operation status="success" ... id=dad69655-07d0-4daf-a639-b8e3257fa6bd msg...
2019-11-14T20:03:48.908Z  INFO Thread Audit Operation status="success" ... id=67ab8c3b-b57c-4328-b483-81582be0341d msg...
2019-11-14T20:03:48.909Z  INFO Thread Audit ... Operation status="success" ...  id=b0485887-004a-4f55-b287-f5c9cf609787 msg...
2019-11-14T20:03:48.911Z  INFO Thread2 Audit ... Operation status="success" ... id=35ca8c14-757f-474a-a929-494781c4679f msg...
2019-11-14T20:03:48.915Z  INFO Thread2 Audit ... Operation status="failure" ... id=72f73c66-da37-11e9-8d68-005056bce6a5 msg...
2019-11-14T20:03:48.917Z  INFO Thread1 Audit ... Operation status="success" ... id=26ece804-da3a-11e9-bfed-005056bce25b msg...
2019-11-14T20:03:48.919Z  INFO Thread Not ... Operation status="failure" ... id=1b31f53f-66d5-475f-ace3-ed1905e8f818 msg...
2019-11-14T20:03:48.921Z  INFO Thread Not ... Operation status="success" ... id=84ee4947-633f-4ccb-832e-7b380052401c msg...
2019-11-14T20:03:48.948Z  INFO Thread Audit ... Operation status="failure" ... id=26ece804-da3a-11e9-bfed-005056bce25b msg...
2019-11-14T20:03:48.950Z  INFO Thread Audit ... Operation status="success" ... id=8837cb5f-48f5-49db-8ade-a47b96527501 msg...

... 表示这之间可以有任何东西,... 有时也可以是一个空格。

msg...表示id并不总是在行尾,msg...有时也可以为null。

实际上它很复杂,但基本结构是这样的。

输入 - 我的输入是给定的 id。

条件 - 条件是查看包含此 id 的日志行,其 OPstatus 为失败且属于 Audit 类。

找到这个日志行后,选择它的线程并获取属于该线程的所有日志,直到该线程的前一个审计日志。

因此,输入是给定的日志行和一个 id = 26ece804-da3a-11e9-bfed-005056bce25b

输出我期待的是这个

2019-11-14T20:03:48.909Z  INFO Thread Audit ... Operation status="success" ...  id=b0485887-004a-4f55-b287-f5c9cf609787
2019-11-14T20:03:48.919Z  INFO Thread Not ... Operation status="failure" ... id=1b31f53f-66d5-475f-ace3-ed1905e8f818 msg...
2019-11-14T20:03:48.921Z  INFO Thread Not ... Operation status="success" ... id=84ee4947-633f-4ccb-832e-7b380052401c msg...
2019-11-14T20:03:48.948Z  INFO Thread Audit ... Operation status="failure" ... id=26ece804-da3a-11e9-bfed-005056bce25b msg...

我试过的是这个-

awk '{if($0~/.*Audit.*26ece804-da3a-11e9-bfed-005056bce25b.*/) system("grep -w " $3 " " FILENAME "| sed \"0,/.*Audit.*Operation status="success".*/d\" | sed \"/Operation status="failure"/{n;d;}\"" )}' file.log

请帮忙!

最佳答案

Perl 助你一臂之力!

perl -lane 'push @{ $h{ $F[2] } }, $_;
     if ("Audit" eq $F[3]) {
         print join "\n", "", @{ $h{ $F[2] } } if /status="failure"/;
         splice @{ $h{ $F[2] } }, 0, -1;
     }' -- file.log
  • -n 逐行读取输入
  • -l 从输入中删除换行符并将它们添加回输出
  • -a 将空格上的输入拆分为 @F 数组
  • 每一行都存储到以线程名称为键的散列(第三列,即$F[2])
  • 如果第四列 $F[3]Audit 并且该行包含失败通知,我们将打印同一线程的所有先前记录的审计行<
  • 向散列添加新的审计行时,我们会删除所有以前的审计行(参见 splice)

换句话说,我们存储每个线程名称的所有审计行,并为每个失败的审计打印之前的行。

关于bash - 从文件中的特定行以相反的顺序 Grep 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61362901/

相关文章:

perl - 我需要重置 Perl 哈希索引吗?

perl - Perl 脚本错误; "Uninitialized Value"?;

awk - 匹配单独文件中的数据

regex - 使用 Bash (sed?) 删除包含特定文本的多行/* ... */样式注释(正则表达式)

c++ - OpenMP C++ GCC 基本例程

perl - 我应该如何修改原型(prototype)以允许在 coderef 之后构造散列?

linux - 如何在给定的时间间隔内测试每行两个条目?

bash - 将文本文件从包含 X 的行剪切到包含 Y 的第一行

linux - 检查 bash 脚本(由 cron 作业运行)是否在 Openshift 中运行

bash - 将相似的文件名描述为一个字符串,用逗号分隔,不同的文件名用空格分隔