Bash 按与文件中特定行相反的顺序Grep文件

Bash 按与文件中特定行相反的顺序Grep文件,bash,perl,awk,sed,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 m

我有这种原木

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…
有时也可以为空

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

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

条件-条件是查看包含该id的日志行,该id的OPstatus为failure,属于审核类

找到此日志行后,选择它的线程,并获取属于该线程的所有日志,直到该线程的上一个审核日志

因此,输入是给定的日志行和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

请帮忙

这适用于您的特定示例:

grep.“*Thread.*=\(success\\ failure\)”filename.txt
。。。给出:

2019-11-14T20:03:48.909Z  INFO Thread Audit OPstatus = success
2019-11-14T20:03:48.919Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.921Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.948Z  INFO Thread Audit Opstatus = failure
但是,您可能希望在今后的bash脚本中对此进行概括。 . Regex101是一个很好的工具,可以为类似的问题找到解决方案

编辑: 要有条件地执行此操作,只需将其放入bash脚本中:

#/usr/bin/env bash
grep-q“*$1.*=failure”$2
如果[$?-等式0];然后
grep“*$1.*=\(成功\ \失败\)”2美元
fi
并运行例如:
/check.sh Thread filename.txt

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
    ,并且该行包含故障通知,我们将为同一线程打印以前记录的所有审核行
  • 在向哈希中添加新的审核行时,我们会删除所有以前的审核行(请参阅)
换句话说,我们存储每个线程名称的所有审核行,并为每个失败的审核打印以前的行。

使用
awk

awk '{if($NF=="failure") system("grep -w " $3 " "  FILENAME)}'  filename.txt
演示:

说明:



NF
你想找到上一次审核吗,即使它也是失败的?另外,一个线程可以有两个以上的审核记录吗?当每一行都匹配时,进行审核有什么意义?@Shawn:“NotAudit”可能原本是其他内容。是的,如果它也是失败的,我想找到上一次审核。是的,一个线程可以有两个以上的审计记录是的,NotAudit是另外一个东西。我们不能像
grep(从某一行向后)线程(直到下一个审计)filename.txt
@BinglerBingler:grep只看到一行,它不能向后或记住上下文。编辑了我的问题,为了让你更好地理解它,我只是在打印该线程以前的审计日志。我也不需要审核该线程的日志。就像我给出的结果一样。哎哟,所以我误解了这个问题。请稍等片刻,然后…如果
Opstatus=failure
@DigvijayS ahh您是对的,您想动态搜索!我已经更新了我的答案来解决这个问题。谢谢。@Yasen no这将检查失败的审核日志,如果是,它将查找该特定线程的所有其他事件。也就是说,如果它发现一个给定线程的
Opstatus=failure
,它就会提取该线程的所有信息。如果日志行在失败后扩展,该怎么办。就我而言,确实如此。我不能只为if条件匹配一些正则表达式“OPstatus=failure”吗?是的/正则表达式/~$0实际上这是可行的,但我只希望线程记录审计失败以上的日志,而不是下面的日志。这个
awk'{if($NF==“failure”)系统(“grep-w“$3”FILENAME)}”file1.txt
命令提供整个进程中的所有线程日志file@BinglerBingler尝试
awk'{if($NF==“failure”)系统(“grep-w“$3”FILENAME“| sed/“$3”.*failure/d”)}file.txt
它仍然给出故障日志下面的日志行
$cat file1.txt
2019-11-14T20:03:48.909Z  INFO Thread Audit OPstatus = success
2019-11-14T20:03:48.911Z  INFO Thread2 Audit OPstatus = success
2019-11-14T20:03:48.915Z  INFO Thread2 NotAudit OPstatus = success
2019-11-14T20:03:48.917Z  INFO Thread1 NotAudit OPstatus = success
2019-11-14T20:03:48.919Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.921Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.948Z  INFO Thread Audit Opstatus = failure
$awk '{if($NF=="failure") system("grep -w " $3 " "  FILENAME)}'  file1.txt
2019-11-14T20:03:48.909Z  INFO Thread Audit OPstatus = success
2019-11-14T20:03:48.919Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.921Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.948Z  INFO Thread Audit Opstatus = failure
$
awk '{if($NF=="failure") system("grep -w " $3 " " FILENAME "| sed \"0,/Audit OPstatus.*success/d\" | sed \"/failure/{n;d;}\"" )}'
$awk '{if($NF=="failure") system("grep -w " $3 " " FILENAME "| sed \"0,/Audit OPstatus.*success/d\" | sed \"/failure/{n;d;}\"" )}' file1.txt 
2019-11-14T20:03:48.909Z  INFO Thread Audit OPstatus = success
2019-11-14T20:03:48.919Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.921Z  INFO Thread NotAudit OPstatus = success
2019-11-14T20:03:48.948Z  INFO Thread Audit Opstatus = failure
$