代码之家  ›  专栏  ›  技术社区  ›  SpaceTrucker

应该使用什么正则表达式来匹配多行日志消息?

  •  1
  • SpaceTrucker  · 技术社区  · 8 年前

    我正在编写一个批处理文件,用于处理我的应用程序的日志文件。

    日志文件可能包含开头与正则表达式匹配的消息 ^.{24}\[ERROR 后面是一些我需要找到的连续行。日志消息的结束将由正则表达式的下一个匹配项表示 ^.{24}\[[A-Z

    (?m)^.{24}\[ERROR(.*\r?\n?.)*?^.{24}\[[A-Z] 以查找此类消息。但是性能非常差,因为它目前已经为几个MB的日志文件运行了几分钟。

    我使用的完整批处理文件是:

    @Echo off
    
    powershell -Command "& {[System.Text.RegularExpressions.RegEx]::Matches([System.IO.File]::ReadAllText('application.log'), '(?m)^.{24}\[ERROR(.*\r?\n?.)*?^.{24}\[[A-Z]') | Set-Content result.txt}"
    

    我应该使用什么正则表达式来匹配上述日志消息?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Wiktor Stribiżew    8 年前

    关键是您的正则表达式包含 (.*\r?\n?.)*? 部分,包含嵌套的可选(即匹配空文本)子模式。一旦在一个组中量化,正则表达式引擎就会在承认没有匹配之前尝试许多组合,从而导致灾难性的回溯或超时问题。

    其中一个解决方案就是使用带有DOTALL修饰符的惰性点匹配模式:

    (?ms)^.{24}\[ERROR(.*?)^.{24}\[[A-Z]
    

    请参阅 regex demo

    NET正则表达式引擎处理子模式的能力要比PCRE、Python-re、JavaScript好得多。

    然而,惰性匹配会降低性能,最好将其展开。我建议

    (?m)^.{24}\[ERROR(.*(?:\n(?!.{24}\[[A-Z]).*)*)\n.{24}\[[A-Z]
    

    看见 another regex demo

    请注意,这两个参数在匹配方面是相同的,但在 怎样 它们匹配。当第一个尝试匹配模式的尾部并在失败时逐个扩展1个字符时,展开的模式只是将文本部分抓取到一个换行符,并且所有没有24个非换行符的换行符都后跟 [ 和大写ASCII字母,即 更快 .

    RegexHero。净测试:

    enter image description here