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

Regex match last occurrence of a string from multiple lines

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

[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...

以上是示例日志文件,其中出现了 3 次以下字符串,

Moving message 123456789 from NEW to PENDING

我需要匹配最后一次出现以获取相应的时间戳“[03/03/2019 09:16:38] ”。 但是当所有这些都在一行中使用贪婪方法 (.*) 时,它工作正常。但是当它们出现在多行中时,它就不起作用了。我还没有尝试过 multiline (m),因为我不确定如何使用它。有人可以帮我构建正则表达式查询来检索最后一次出现的时间戳吗? 示例:https://regex101.com/r/fnwPsB/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 字符,后跟最后一次出现的后续模式。
  • \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 组中定义的相同模式,则匹配失败的否定前瞻。

这里是一个不依赖于 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) 是负前瞻,确保我们匹配给定模式的最后一次出现。