异常日志的正则表达式

Regex for exception logs

我正在使用 PCRE 在以下正则表达式的帮助下匹配异常日志。

正则表达式

\[([\d -:]+)\]ERROR.*?(F:[^ ]+|F:).*?(?sx).*?(\b[a-zA-Z]*Exception\b)

异常日志示例

  1. 捕获的异常是inline(在一行中)的日志语句

    [2020-03-07 01:02:37.512]ERROR [L:xx F:yy T:zz R: C: ] xxxxxxx xxxxx xxxx xxxx NullPointerException
            at com.package.name(b.java:20)
            at com.package.name.someClass.someMethod(P.java:2423)
            at com.package.name.someClass.someMethod(P.java:40)
            at com.package.name.someClass.someMethod(P.java:4054)
    
  2. 捕获的异常在任何其他下一个日志语句中

    [2020-03-07 01:02:37.512]ERROR [L:xx F:yy T:zz R: C: ] xxxxxxx xxxxx xxxx xxxxxxxx xxxxxxxxxxxxxxxx 
    xxxxxxxxx xxxxxxxxxxx xxxxxxxx xxxx xxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxx xxxx NullPointerException
            at com.package.name(b.java:20)
            at com.package.name.someClass.someMethod(P.java:2423)
            at com.package.name.someClass.someMethod(P.java:40)
            at com.package.name.someClass.someMethod(P.java:4054)
    

第二个样本与提到的正则表达式不匹配。

我也试过使用multi-line flag (\m),但它不会因为它不应该匹配任何东西的情况而停止

例子

[2020-03-07 01:02:37.512]ERROR [L:xx F:yy1 T:zz1 R: C: ] xxxxxxx xxxxx xxxx xxxx
[2020-03-07 01:03:37.512]ERROR [L:xx F:yy2 T:zz2 R: C: ] xxxxxxx xxxxx xxxx xxxx
[2020-03-07 01:04:37.512]ERROR [L:xx F:yy3 T:zz3 R: C: ] xxxxxxx xxxxx xxxx xxxx 
[2020-03-07 01:05:37.512]ERROR [L:xx F:yy4 T:zz5 R: C: ] NullPointerException
            at com.package.name(b.java:20)
            at com.package.name.someClass.someMethod(P.java:2423)
            at com.package.name.someClass.someMethod(P.java:40)
            at com.package.name.someClass.someMethod(P.java:4054)

预期结果

Group 1: 2020-03-07 01:05:37.512, Group 2: F:yy4, Group 3: NullPointerException

实际结果

Group 1: 2020-03-07 01:02:37.512 Group 2: F:yy1 Group 3: NullPointerException

看看在匹配第一行后它如何在找到完整的表达式之前不会停止。

有人可以帮我解决这个问题吗?

您可以从模式的开头检查下一行不是以 [ 开头的,并且使用内联修饰符 (?!.*\R\[\d) 时使用负先行 (?!.*\R\[\d) 的数字14=]之后。

这部分 (F:[^ ]+|F:) 可以缩短为匹配 F: 和 0+ 次非空白字符 (F:\S*)

在字符 class [\d -:] 中,连字符匹配一个范围,而不仅仅是一个连字符字符。如果你想从字面上匹配它,你可以将它移到最后并添加匹配点。

^(?!.*\R\[\d)\[([\d :.-]+)]ERROR.*?(F:\S*)(?sx).*?\b([a-zA-Z]*Exception)\b

说明

  • ^ 字符串开头
  • (?!.*\R\[\d) 否定前瞻,断言下一行不以 [\R 匹配 unicode 换行序列
  • 的数字开头
  • \[ 匹配 [
  • ([\d :.-]+) 捕获 组 1,匹配任何列出的
  • ] 匹配 ]
  • ERROR.*? 匹配 ERROR 和 0+ 次除换行符外的任何字符
  • (F:\S*) 捕获 组 2,匹配 F: 和 0+ 次非空白字符
  • (?sx).*? 内联修饰符 s 使点匹配换行符 x 忽略空格
  • \b([a-zA-Z]*Exception)\b 捕获 组 3,匹配 0+ 次字符 a-zA-Z 后跟异常

Regex demo

另一个不使用内联修饰符 s 使点匹配换行符的选项可以是在匹配 ERROR 和 F: 部分后选择性地匹配所有不包含 Exception 的行。

^(?!.*\R\[\d)\[([\d :.-]+)]ERROR.*?(F:\S*)(?:(?!.*Exception|.*\R\[\d).*\R)*+.*\b([a-zA-Z]*Exception)\b

Regex demo