正则表达式匹配多行中最后一次出现的字符串

时间:2019-03-05 10:55:21

标签: regex regex-greedy

我正在尝试匹配日志文件中最后一次出现的字符串。

[03/03/2019 09:16:36] Moving message 123456789 from NEW to PENDING
[03/03/2019 09:16:36] Retrieving file(s) of type DATAWAREHOUSE for 123456
[03/03/2019 09:16:36] collecting warehouse version 7.3.1 files for 123456...
[03/03/2019 09:16:37] Moving message 123456789 from NEW to PENDING
[03/03/2019 09:16:37] Retrieving file(s) of type DATAWAREHOUSE for 123456
[03/03/2019 09:16:37] collecting warehouse version 7.3.1 files for 123456...
[03/03/2019 09:16:38] Moving message 123456789 from NEW to PENDING
[03/03/2019 09:16:39] Retrieving file(s) of type DATAWAREHOUSE for 123456
[03/03/2019 09:16:40] collecting warehouse version 7.3.1 files for 123456...

上面是示例日志文件,在该示例日志文件中,以下字符串出现了三遍,

Moving message 123456789 from NEW to PENDING

我需要匹配最后一次出现以获取相应的时间戳“ [03/03/2019 09:16:38] ”。 但是,如果所有这些都使用贪婪方法(。*)放在一行中,则效果很好。但是,当它们以多行显示时,它将无法正常工作。我没有尝试过多行(m),因为我不确定如何使用它。有人可以帮我构造正则表达式查询以检索此最后一次出现的时间戳吗? 示例:https://regex101.com/r/fnwPsB/1

2 个答案:

答案 0 :(得分:1)

您可以使用

(?s:.*\n)?\K\[(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2})\] Moving message 123456789 from NEW to PENDING

请参见regex demo

详细信息

  • (?s:.*\n)?-一个内联修饰符组,该组修饰符尽可能匹配任意0+个字符,直到最后一个LF字符为止,最后一个LF字符与随后出现的后续模式相同。
  • \K-匹配重置运算符从匹配内存缓冲区中删除到目前为止所有匹配的文本
  • \[(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2})\] Moving message 123456789 from NEW to PENDING-与第1组中捕获的日期时间对应的特定线型。

或者,使用

(?s)(\[\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2}\] Moving message 123456789 from NEW to PENDING)(?!.*(?1))

请参见this regex demo

详细信息

  • (?s)-DOTALL修饰符使.匹配任何字符
  • (\[(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2})\] Moving message 123456789 from NEW to PENDING)-匹配捕获到第1组和第2组中的日期时间的必要模式
  • (?!.*(?1))-如果在当前位置右侧的任何0+个字符后,如果与第1组中定义的模式相同,则否定超前行为将使匹配失败。

答案 1 :(得分:1)

以下是使用负前瞻不依赖于PCRE功能的解决方案:

(?s)\[(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2})\] Moving message 123456789 from NEW to PENDING(?!.* Moving message 123456789 from NEW to PENDING)

RegEx Demo

第一个捕获组中的日期时间。

这里(?!.* Moving message 123456789 from NEW to PENDING)为负向超前,可确保我们匹配给定模式的最后一次出现。