正则匹配单行/多行日志:message分组需捕获换行至下一时间戳
多行日志匹配正则方案
问题背景
解析同时包含单行、多行格式的日志文件时,原有正则仅能匹配单行日志,无法适配多行场景:
- 原有正则表达式:
^(?<timestamp>\d+-\d+-\d+T\d+:\d+:\d+\.\d+(\+|-)\d+:\d+)\s+\[(?<severity>\w+)\](?<message>.*)$
- 匹配失败场景:当日志消息体包含换行内容时,正则无法捕获换行后的内容,典型多行日志样例如下:
2022-06-27T15:22:35.508+00:00 [Info] New settings received: {"indexer.settings.compaction.days_of_week":"Sunday,Monday"}
- 目标要求:
<message>命名分组需完整包含换行后的内容,持续匹配直到检测到下一条日志的时间戳为止。
可用正则实现
正则表达式
使用时需开启多行匹配模式(m标志),正则内容如下:
^(?<timestamp>\d+-\d+-\d+T\d+:\d+:\d+\.\d+[+-]\d+:\d+)\s+\[(?<severity>\w+)\](?<message>[\s\S]*?)(?=^\d+-\d+-\d+T\d+:\d+:\d+\.\d+[+-]\d+:\d+|\Z)
逻辑说明
- 时间戳、日志级别的匹配逻辑和原有正则保持一致,将时间戳部分的
(\+|-)简化为字符组[+-],匹配效率更高 <message>分组使用[\s\S]*?匹配内容:[\s\S]可覆盖包括换行符在内的任意字符,*?为惰性匹配规则,会尽可能少匹配字符,直到触发后续终止边界- 末尾前瞻断言定义匹配终止边界,满足任意一个条件即停止当前日志message的匹配:
- 检测到行首位置出现符合格式的下一条日志时间戳
- 到达整个待匹配文本的末尾(锚点
\Z),保证最后一条日志不会被截断
注意事项
- 不要直接给原有正则的
.*开启单行模式(s标志,让.匹配换行),默认贪婪匹配规则会把后续所有日志内容都吞入第一条日志的message分组,导致匹配错乱 - 若使用的正则引擎不支持
\Z文本末尾锚点,可将其替换为$,保持多行模式开启即可正常匹配最后一条日志 - 该写法兼容Python、Java、C#、ES2018+版本JavaScript等所有支持命名分组、前瞻断言的现代正则引擎。
内容的提问来源于stack exchange,提问作者Xhens
相关产品推荐
相关产品推荐

