我正在编写一个处理我的应用程序日志文件的批处理文件。
日志文件可能包含其开头与正则表达式^.{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}"
我应该使用什么正则表达式来匹配上面描述的日志消息?
答案 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]
请注意,这些2与它们匹配的内容相同,但 匹配的方式不同。当第一个尝试匹配模式的尾随部分并在失败时将1个字符扩展为1时,展开的模式仅将文本部分抓取到换行符,并且所有没有24个非换行符号的换行符后跟{{1}和一个大写的ASCII字母,更快。
RegexHero.net测试: