如何编写正则表达式正确提取Java日志中带堆栈的完整ERROR日志
Java带堆栈ERROR日志块正则提取最优实现
核心正则表达式
直接用下面的正则即可,覆盖所有常见日志场景,无冗余写法:
\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}\sERROR[\s\S]*?(?=\n\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}|\Z)
如果用Python编写,raw字符串写法为:
ERROR_LOG_REG = r'\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}\sERROR[\s\S]*?(?=\n\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}|\Z)'
规则拆解
- 起始锚定:
\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}\sERROR精准匹配标准日期时间开头的ERROR日志行,不会误匹配日志正文里的ERROR关键字。 - 内容匹配:
[\s\S]*?是解决之前冗余、匹配不全问题的核心:- 用
[\s\S]代替.+换行符的拼接写法,可以直接匹配所有字符包括换行,同时兼容堆栈行用空格/制表符缩进的不同格式,不需要单独写换行、缩进的重复规则。 - 用
*?非贪婪匹配,解决贪婪匹配导致的“仅匹配到最后一段内容”的问题——非贪婪模式会匹配到第一个终止条件就停止,不会无限制向后吞内容。
- 用
- 终止判断:
(?=\n\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}|\Z)用正向零宽断言做终止判断,不会把下一条日志的开头纳入匹配结果,同时覆盖两种场景:- 碰到下一条带标准日期前缀的新日志时停止
- 匹配到整个日志文件末尾(
\Z)时停止,不会漏掉文件最后一条ERROR日志
按需调整版本
如果需要严格过滤掉不带堆栈跟踪的ERROR日志,只需要在正则中加入Java堆栈固定存在的at调用行特征即可:
\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}\sERROR[\s\S]*?\n\s*at\s[\s\S]*?(?=\n\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}|\Z)
这个版本会自动跳过只有一行错误信息、没有堆栈的ERROR日志,完全匹配提取需求。
匹配效果验证
用提供的示例日志做匹配,返回结果正好是从ERROR起始行到DEBUG行之前的完整堆栈块,不会截断内容也不会带上后续其他级别的日志。
内容的提问来源于stack exchange,提问作者user388794
相关产品推荐
相关产品推荐

