惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
罗磊的独立博客
SecWiki News
SecWiki News
The Register - Security
The Register - Security
The GitHub Blog
The GitHub Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
IT之家
IT之家
博客园 - 聂微东
T
The Exploit Database - CXSecurity.com
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Vercel News
Vercel News
G
GRAHAM CLULEY
D
DataBreaches.Net
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
SegmentFault 最新的问题
博客园_首页
雷峰网
雷峰网
T
Tenable Blog
Spread Privacy
Spread Privacy
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
Cisco Talos Blog
Cisco Talos Blog
V
Visual Studio Blog
J
Java Code Geeks
博客园 - Franky
The Cloudflare Blog
Apple Machine Learning Research
Apple Machine Learning Research
C
CERT Recently Published Vulnerability Notes
T
Threatpost
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
V
Vulnerabilities – Threatpost
Recent Announcements
Recent Announcements
Blog — PlanetScale
Blog — PlanetScale
Security Latest
Security Latest
U
Unit 42
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
K
Kaspersky official blog
有赞技术团队
有赞技术团队
B
Blog
腾讯CDC

Measure Zero

读 Codex 源码 - memory 机制 读论文 - EnterpriseRAG-Bench 【机翻】语音智能体基础 101:能够与人对答的 AI 背后的架构 【机翻】语音智能体中的记忆问题比你想象的更难 读 Claude Code 源码 - 若干小功能 (recap, suggestion, insights) 【机翻】大多数 AI 产品不应该推出记忆功能 如何评估 skill Langchain 团队如何评估与优化 agent harness 读 Claude Code 源码 - memory 机制续篇 Harness Cheatsheet 读 Claude Code 源码 - Web Search & Web Fetch 难倒各路大模型的两道简单 SQLite 问题 ModernBERT
去年遇到的一个正则的坑
Shiina · 2026-05-03 · via Measure Zero

去年遇到的一个正则的坑

去年排查过一个性能问题. 一个包含很多正则替换的函数, 在处理几十万字符长度的文本时, 跑了 10 秒才完成. 最后定位到问题正则形式如下:

\s*xyz blahblah

几年前排查过 灾难性回溯 问题, 但这个正则的结构其实完全没有相关特征. 如果真的是灾难性回溯, 处理几十万字符的字符串早就卡死了, 而不是只跑 10 秒.

最后解决方案是先用

xyz blahblah

找 match, 再处理 leading spaces. 时延是毫秒内.

首字符优化

正则表达式引擎有一个核心优化技术——初始字符/类/子串区分优化 (Initial character/class/substring discrimination optimization). 下面内容参考 Mastering Regular Expressions.

现代正则表达式引擎在编译正则表达式时, 会进行一系列静态分析. 其中最重要、也是效果最显著的一项分析就是: 确定任何匹配这个正则表达式的字符串, 必须以哪些字符或子串开头.

如果引擎能够确定这一点, 它就不会在字符串的每个位置都尝试完整匹配正则表达式, 而是会采用一个极其高效的两步策略:

  1. 使用高度优化的原生字符串扫描算法 (通常是 Boyer-Moore 或其变种) 快速定位所有可能的候选起始位置
  2. 只在这些候选位置上尝试完整匹配正则表达式

对于正则表达式 xyz blahblah, 引擎很容易分析出: 任何匹配都必须以字符 x 开头. 因此, 它会先在整个字符串中快速扫描所有 x 出现的位置. 如果一个几十万字符的字符串中只有 3 个 x, 那么它只需要在这 3 个位置尝试匹配后续的 yz blahblah, 而不是在几十万个位置都尝试一次.

为什么 \s* 会彻底破坏这个优化? 问题就出在 \s* 这个前导空白字符匹配上. 因为 “零个空白字符” 是完全合法的匹配, 每个字符位置都可能是匹配的起点. 当正则表达式以无锚点的 \s*.*.*? 这类通用量词开头时, 引擎无法确定任何必须的起始字符. 它只能退回到最原始、最低效的匹配方式: 在字符串的每一个字符位置上, 都从头开始尝试完整匹配整个正则表达式.

正则引擎的其他相关优化

1. 必需字符/子串预检查优化

这是首字符优化的更通用版本. 引擎不仅会分析起始字符, 还会分析整个正则表达式中必须出现的任何字符或子串, 无论它们出现在什么位置.

在实际应用正则表达式之前, 引擎会先快速检查目标字符串中是否包含这些必需字符或子串. 如果不包含, 就可以直接跳过整个正则匹配过程, 节省大量时间.

例如, 对于正则表达式 ^Subject: (.*), 引擎会发现字符串 Subject: 是任何匹配都必须包含的. 它可以使用 Boyer-Moore 算法快速搜索整个字符串, 如果找不到 Subject:, 就直接返回不匹配.

2. 长度认知优化

引擎还会分析正则表达式的最小匹配长度. 如果目标字符串的长度小于这个最小长度, 就可以直接跳过匹配.

例如, ^Subject: (.*) 的最小匹配长度是 9 个字符 (“Subject: “). 因此, 对于任何长度小于 9 的字符串, 引擎都不需要启动完整的匹配过程. 对于那些有很长固定后缀的正则表达式 (如 :\d{79}:), 这个优化的效果会更加明显.

3. 不同引擎的实现差异

需要特别注意的是, 不同的正则表达式引擎在这些优化的实现程度上有非常大的差异:

  • 大多数现代引擎都能很好地处理简单的固定前缀优化
  • 但对于包含交替 (|) 的复杂表达式, 很多引擎无法推导出共同的起始字符
  • 例如, 对于 this|that|other, 一些引擎只能推导出起始字符是 [ot], 而无法推导出更复杂的模式
  • 这也是为什么书中建议使用 th(is|at) 代替 this|that, 这样引擎可以更容易地推导出共同前缀 th