我正在编写一个批处理文件来处理我的应用程序的日志文件。
日志文件可能包含开头与正则表达式 ^.{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}"
如上所述,我应该使用什么正则表达式来匹配日志消息?
最佳答案
重点是您的正则表达式包含 (.*\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]
请注意,这 2 个在它们匹配的内容上是等价的,但在它们匹配的方式上不同。虽然第一个尝试匹配模式的尾部并在失败时将 1 个字符扩展一个,但展开的模式只是抓取文本部分直到换行符,所有没有 24 个非换行符的换行符后跟 [
和一个大写 ASCII 字母,这样更快。
RegexHero.net 测试:
关于c# - 应该使用什么正则表达式来匹配多行日志消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38873769/