perl 多行问题:需要一个衬里来打印文件中字符串之前的最后一个匹配项

perl multiline issue: need one liner to print last match before string in file

我有一个这样的日志文件:

2018-07-10 10:03:01: random text1
2018-07-10 10:03:02: random text2
2018-07-10 10:03:03: random text3
    more text
    and more
    THIS IS MATCHED STRING
2018-07-10 10:03:04: random text4

我想使用 perl 单行查找 "THIS IS MATCHED STRING" 之前的最新时间戳。

我试过这个:

perl -0777 -nle 'print "\n" while m/(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).+?THIS IS MATCHED STRING/sg'

但它匹配了第一个时间戳,“2018-07-10 10:03:01”,而不是我想要的“2018-07-10 10:03:03”。显然(至少我认为),我不太了解 greedy/lazy 匹配的工作原理。

如有任何帮助,我们将不胜感激!

你可以使用

^
(\d{4}-\d{2}-\d{2}\ \d+:\d+:\d+):
(?:(?!^\d{4})[\s\S])+?
\QTHIS IS MATCHED STRING\E

a demo on regex101.com

对于一个相当基本的方法,它避免了涉及的正则表达式,逐行处理,并在时间戳模式匹配时记录它。然后,当您 运行 进入模式 THIS... 时,您将拥有(最后的)前一个时间戳。

perl -wnE'
    $ts =  if /(\d{4}-\d{2}-\d{2}[ ]\d{2}:\d{2}:\d{2})/; 
    say $ts // "no previous time stamp"  if /THIS IS MATCHED STRING/;
' file.txt

如果时间戳被捕获并用 ($ts) = /.../ 保存,那么在没有它的情况下在行上匹配失败 undef,所以当找到 THIS 时它可能不存在。因此只有在匹配时才会从 </code> 中保存。</p> <p><code>$ts 上的定义或 (//) 用于防止文件在 THIS

之前根本没有时间戳