^\s*at\s+ 是定位堆栈行的可靠锚点,因其能精准匹配java异常堆栈中以可变空白符开头、后接at及类名方法签名的标准格式(如at com.example.service.handle(service.java:42)),既避开日志前缀干扰,又兼容缩进,且覆盖主体调用链而非仅caused by起点。

为什么 ^\s*at\s+ 是定位堆栈行的可靠锚点
日志里错误堆栈通常以 at 开头、缩进可变、后面紧接类名和方法签名,比如 at com.example.Service.handle(Service.java:42)。用 ^\s*at\s+ 能避开日志前缀(如时间戳、线程名)干扰,同时兼容空格或制表符缩进。别用 ^at——它会漏掉被缩进的嵌套调用;也别依赖 Caused by,那只是异常链起点,不是堆栈主体。
实操建议:
- 确保 Sublime 的替换模式设为「正则表达式」(右下角勾选
. *图标) - 搜索框填:
^\s*at\s+([^\n]+),捕获组留着后续提取用 - 如果日志混有非 Java 堆栈(如 Node.js 的
at Object.),需微调为^\s*at\s+(?!Object\.|Function\.)排除干扰
用 \K 丢弃前缀,只保留关键路径和行号
直接匹配整行再替换,容易把缩进和 at 一起带进来。Sublime 支持 PCRE 风格的 \K,它能“丢弃此前所有匹配内容”,让替换结果更干净。比如从 at com.example.Dao.query(Dao.java:105) 中只取 Dao.java:105。
实操建议:
- 搜索:
^\s*at\s+[^\(]+\(([^)]+)\)→ 替换为:$1,但会多出包名路径 - 更精准的写法:
^\s*at\s+[^\(]+\([^)]*?([^)]*?\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.java:\d+)\)太绕,易错 - 推荐方案:搜索
^\s*at\s+[^\(]+\(\K[^)]+\.java:\d+,替换为空(即只留下.java文件名+行号) - 注意:
\K在 Sublime 中需开启「PCRE 模式」,默认已启用;若无效,检查是否误开了「字面量」模式
一次性提取完整堆栈块,避免单行匹配断裂
单行匹配 at 会把一个异常的多层调用拆成零散行,丢失上下文。要提取“从 Exception 行开始,到下一个空行或新日志时间戳为止”的整个块,得靠多行匹配逻辑。
实操建议:
- 搜索:
(?s)Exception[^]*?(?=\n\s*\n|\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}|\z),其中(?s)启用 dotall 模式使.匹配换行符 - 若日志无空行分隔,改用时间戳识别:
(?s)Exception[^]*?(?=\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}|\z) - 替换时用
$0或直接复制,别误操作成空——否则整块消失 - 性能提示:大日志文件(>10MB)上此正则可能卡顿,先用
Ctrl+G跳到首个Exception再局部运行
导出后快速去重并按文件/行号排序
提取出的 Dao.java:105 类路径行号列表,重复项多且顺序乱。Sublime 本身不支持排序去重,但可借力命令行或内置功能快速收尾。
实操建议:
- 全选提取结果 →
Ctrl+Shift+P→ 输入Sort Lines→ 回车(升序) - 去重:先排序,再搜索
^(.*)(\n\1)+$,替换为$1(注意勾选「正则」和「跨行」) - 更稳的去重方式:复制内容到新标签页 →
Ctrl+Shift+P→Remove Duplicate Lines(需安装 Package Control 的同名插件) - 如果需要按行号数字排序(而非字符串),得导出后用
sort -t: -k2,2n(Linux/macOS)或 PowerShell 的Sort-Object { [int]$_.Split(':')[1] }
真正麻烦的不是匹配,而是日志格式不统一:有些堆栈没 at(如 Kotlin 的 Caused by: java.lang.NullPointerException 直接跟描述),有些用 at 但括号里是 lambda 符号。这类得人工过一遍,正则只能覆盖 80% 的规整场景。









