如何在第一次匹配后使用正则表达式检查多行文本,并且仅在第二次匹配之前检查

时间:2018-02-09 11:29:29

标签: regex grep pattern-matching pcre

我试图在一个相当大的日志文件中找到所需的日志(让我们说250 MB)。 每个日志都以

开头
  

YYYY-MM-DD时间:

接下来是一些一行或多行文字 我想要匹配

最后以换行符和新的DateTime模式结束。

问题是如果日志中的文本是多行并且仅在下一个日志之前,如何匹配日志。 匹配值的顺序未知以及它们的行。

我尝试了下一个解决方案

grep -Pzio '^(\d{4}-\d{2}-\d{2} timePattern)(?=[\s\S]*?Value1)(?=[\s\S]*?Value2)(?=[\s\S]*?Value3)[\s\S]*?(?=(\n\1|\Z)' file.log

但即使使用了不合格的[\s\S]*?,也只是获得了以前不匹配的日志,并且在[\s\S]*中包含了很多其他日志,最后找到所有三个值之前匹配第一次抓捕小组,只是给了我大量的文字。

所以唯一的困难是多线,我想在这里。 将不胜感激任何帮助!

编辑0:我只需找到一个包含我尝试匹配的所有值的日志。

编辑1:示例

2018-02-09 03:52:46,347 Activity=SomeAct
@Request=<S:Body><S:RQ><S:Info><S:Key><S:First>Value1</S:First><S:Second>Value2</S:Second></S:Key></S:Info></S:RQ></S:Body>
@Response=<SOAP-ENV:Body><S:RS><S:StatusCode>FAILURE</S:StatusCode></S:RS></SOAP-ENV:Body>
2018-02-09 03:52:51,377 Activity=SomeAct
@Request=<S:Body><S:RQ><S:Info><S:Key><S:First>Value1</S:First><S:Second>Value2</S:Second></S:Key></S:Info></S:RQ></S:Body>
@Response=<SOAP-ENV:Body><S:RS><S:StatusCode>SUCCESSFUL</S:StatusCode></S:RS></SOAP-ENV:Body>
2018-02-09 03:52:52,112 Activity=SomeAct
@Response=<SOAP-ENV:Body><S:RS><S:StatusCode>FAILURE</S:StatusCode></S:RS></SOAP-ENV:Body>
@Request=<S:Body><S:RQ><S:Info><S:Key><S:First>Value1</S:First><S:Second>Value3</S:Second></S:Key></S:Info></S:RQ></S:Body>

我只需要在SUCCESFULL状态下获取value1和value2的记录。 但是没有必要在请求之后做出响应,或<first><second>或RS \ RQ之前只有一行。

1 个答案:

答案 0 :(得分:1)

它不是很清楚您想要找到什么,但常见的方法是将Awk与自定义记录分隔符一起使用,以便记录可以是多行。或者您可以手动收集记录:

awk '/^YYYY-MM-DD time: / { if (seen1 && seen2 && seen3) print rec;
        seen1 = seen2 = seen3 = 0; rec = "" }
    { rec = (rec ? rec "\n" $0 : $0 }
    /Value1/ { seen1++ }
    /Value2/ { seen2++ }
    /Value3/ { seen3++ }
    END { if (seen1 && seen2) print rec; }' file

这会收集rec自上一个分隔符后我们看到的行,当我们看到一个新的分隔符时,我们会在重新开始之前从rec打印前一个值,如果所有&#34;看到&#34;设置了标志,表示我们已将所有正则表达式与当前rec中的文本进行匹配。

当我们到达文件末尾时,常见的遗漏是忘记在END块中执行此操作。