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

时间:2016-08-10 12:42:20

标签: c# regex powershell batch-file

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

日志文件可能包含其开头与正则表达式^.{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 个答案:

答案 0 :(得分:3)

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

其中一个解决方案就是使用延迟点匹配模式和DOTALL修饰符:

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

请参阅regex demo

.NET正则表达式引擎比PCRE,Python,JavaScript更好地处理子模式。

然而,懒惰匹配会降低性能,最佳实践是展开它。我建议

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

请参阅another regex demo

请注意,这些2与它们匹配的内容相同,但 匹配的方式不同。当第一个尝试匹配模式的尾随部分并在失败时将1个字符扩展为1时,展开的模式仅将文本部分抓取到换行符,并且所有没有24个非换行符号的换行符后跟{{1}和一个大写的ASCII字母,更快

RegexHero.net测试:

enter image description here