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

推荐订阅源

The Last Watchdog
The Last Watchdog
博客园_首页
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
美团技术团队
小众软件
小众软件
V
V2EX
博客园 - Franky
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The GitHub Blog
The GitHub Blog
Microsoft Security Blog
Microsoft Security Blog
Attack and Defense Labs
Attack and Defense Labs
S
Security Affairs
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
T
The Exploit Database - CXSecurity.com
有赞技术团队
有赞技术团队
S
Schneier on Security
人人都是产品经理
人人都是产品经理
Security Archives - TechRepublic
Security Archives - TechRepublic
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
K
Kaspersky official blog
PCI Perspectives
PCI Perspectives
AI
AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
罗磊的独立博客
O
OpenAI News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Register - Security
The Register - Security
V
Vulnerabilities – Threatpost
GbyAI
GbyAI
博客园 - 【当耐特】
C
Cisco Blogs
大猫的无限游戏
大猫的无限游戏
Help Net Security
Help Net Security
Google DeepMind News
Google DeepMind News
S
Securelist
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Proofpoint News Feed
博客园 - 三生石上(FineUI控件)
雷峰网
雷峰网
L
LangChain Blog
SecWiki News
SecWiki News
博客园 - 叶小钗
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V2EX - 技术
V2EX - 技术
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
L
LINUX DO - 热门话题
Cisco Talos Blog
Cisco Talos Blog

Measure Zero

读 Agent 新趋势 - goal, loop 和 loop engineering 读 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