首页 › programming › 正则神课:给文本装上搜索引擎

正则神课:给文本装上搜索引擎

导语

程序员圈子里流传一个老段子:「有些人遇到问题时会想,我知道,我用正则表达式。于是他们有了两个问题。」这句话出自 Netscape 早期工程师 Jamie Zawinski 之口,被调侃了几十年,却恰恰证明了一件事:正则这门手艺,人人绕不开,人人头疼过。Fireship(主理人 Jeff Delaney)的《Regular Expressions (Regex) in 100 Seconds》就是把这门手艺浓缩进一百秒的爆款课——上线后播放量达到数百万级(历史公开数据,本次未能实时核实,发布前建议复核),成为无数开发者正则入门的第一站。本文把它当作「目录页」展开成整本书:视频到底讲了什么、这些稀奇古怪的符号从哪来、引擎底层怎么跑、以及它没讲的那条暗坑,如何在 2019 年放倒过半个互联网。

视频基本信息

项目 内容
视频标题 Regular Expressions (Regex) in 100 Seconds(正则表达式一百秒速成)
频道 Fireship(主理人 Jeff Delaney,以「in 100 Seconds」系列与前端圈辣评闻名)
上线时间 2019 年前后,属其「in 100 Seconds」系列走红期(据频道页面归档)
播放量 数百万级(历史公开数据,未能实时核实)
定位 入门速览:语法地图 + 现场代码演示
时长 约 2 分钟

核心内容拆解

① 一句话定义:正则是「文本的查询语言」

视频开场就把定位讲死:正则不是一门编程语言,而是用一串字符描述一个搜索模式的迷你语言(视频复述)。你写下的不是「匹配某个具体字符串」的代码,而是「某一类字符串的共同形状」。比如 \d{3}-\d{4} 描述的不是某一个电话号码,而是「三位的段、一根横杠、四位的段」这一整族号码。

我的延伸分析:这条定义里藏着正则难学的真正原因——它是叠在另一层语言之上的语言。普通字符(字面量)和元字符(控制符)混写在同一行里,同一个符号在不同位置身份不同:a 就是字母 a,. 却是「任意字符」,而 `.又变回了句号本身。这种「一符多义、上下文定身份」的设计,是它表达力恐怖的来源,也是它可读性灾难的根源。

② 语法四件套:一百秒的主体就是一张地图

视频主体是一条极快的现场演示,把语法拆成四组依次亮相(视频复述,个别顺序据画面):

  1. 字符类:\d 匹配数字,\w 匹配字母数字下划线,\s 匹配空白;方括号自定义集合 [a-zA-Z0-9],方括号里开头放尖号 [^0-9] 表示「取反,匹配非数字」;
  2. 量词:* 零个及以上,+ 一个及以上,? 可有可无,{2,4} 指定重复两到四次;
  3. 锚点:^ 锚定行首,$ 锚定行尾,\b 锚定单词边界——锚点不消耗字符,只声明位置;
  4. 分组与分支:圆括号 () 捕获子串供后续提取,竖线 | 表示「或」,(?:...) 只分组不捕获,节省内存也少生噪音。

最后补了两个「改行为」的旗标:g 全局匹配(否则只命中第一处),i 忽略大小写,m 把 ^ $ 的语义从整串扩展到每一行。

我的延伸分析:这张地图的精妙之处在于正交——四件套可以自由组合,一个模式 = 字符类回答「匹配什么」,量词回答「重复几次」,锚点回答「在哪匹配」,分组回答「怎么切出我要的部分」。学会这四件的组合思维,比背一百条实例正则更根本。

③ 演示代码里的门道:为什么偏偏是 JavaScript

视频用 JavaScript 做演示:字面量 /pattern/flags 直接书写,RegExp 构造器动态创建,.test() 返回布尔判断,.match() 提取命中结果(视频复述)。

我的延伸分析:选 JS 不是随意的——正则字面量在 JS 里是语言级一等公民,不需要像 Java 那样写双重转义的地狱字符串。但这也埋了个坑:不同语言里正则的「方言差异」真实存在。Python 的 re、Java 的 java.util.regex、PCRE、Go 的 regexp,语法八成相似,剩下两成(贪婪策略细节、Unicode 支持、是否支持反向引用与环视)各有各的脾气。「学会语法」和「用好正则」之间,隔着的正是这层方言意识。

④ 结尾的姿态:通用,但别滥用

视频收尾强调正则「几乎所有语言、几乎所有编辑器、几乎所有工具链都支持」,值得每个开发者投入(视频复述)——同时也没忘记自嘲那句 two problems 的圈著名梗。

我的延伸分析:这个收尾其实是全片最诚实的一分钟。正则的最佳射程是模式清晰、规模有限、一次性的文本任务:日志抽取、格式校验、编辑器批量替换。一旦模式复杂到需要写注释才有人读懂,或者要处理「理论上无限长」的输入,就该考虑换成普通代码——可读性是生产环境里比简洁更贵的货币。

知识与理论溯源:视频没空讲的家谱

从「神经元的数学」到 grep

正则比个人电脑还年长三十岁,它的家谱每一段都是硬历史:

换句话说,你在视频里看到的 \d 和 *,是一条从神经生理学数学、经贝尔实验室、到万维网基础设施的七十年传承线。

引擎的两条技术路线:回溯 vs 自动机

视频完全没展开、但决定正则生死的,是引擎层:

当暗坑变成事故:Cloudflare 2019 年全球宕机复盘

视频省略的那条暗坑,有一个教科书级的事故现场。据 Cloudflare 官方事后报告:2019 年 7 月 2 日,一条用于 XSS 防护的 WAF(Web 应用防火墙)规则带着嵌套量词的正则上线,在 PCRE2 的回溯引擎上触发灾难性回溯(catastrophic backtracking),全球边缘节点 CPU 被打满,全站大面积返回 502,宕机持续约 27 分钟,波及大量依赖其反代的网站。CTO John Graham-Cumming 发布了详细事后报告,事故后 Cloudflare 的新一代 WAF 引擎改用了 Rust 的线性时间正则库——据其官方博客。

这条暗坑学名 ReDoS(Regular expression Denial of Service),已收入 OWASP 词条。经典触发样例是用模式 ^(a+)+$ 去匹配一长串 a 加一个失败结尾:回溯引擎会把所有分组切分方式试个遍,二十几个字符就能把耗时推到天文数字。无独有偶,2016 年 Stack Overflow 的一次宕机,官方事后也归因于一条失控的正则(据其官方复盘)。

批判性审查:哪些可信,哪些要打折

  1. 「100 秒」是营销不是承诺。 一百秒只够建立语法地图,熟练需要几十次在 regex101 这类工具上的实操打磨。这条视频的真实角色是「系列预告片」——它负责让你产生兴趣,不负责让你学会。把它当目录读,是正确姿势。
  2. 视频对引擎差异完全静默,而这恰是生产环境最大的坑。 语法四件套背得再熟,不知道自己脚下是回溯引擎还是自动机引擎,等于不知道自己写的代码最坏情况是多慢。本文「理论溯源」一节就是给这条补的课。
  3. 正则不是万能锤子。 解析 HTML/XML 是它的经典翻车现场——嵌套结构不是正则语言,Stack Overflow 上「你不能用正则解析 HTML」的名回答(附著名 Zalgo 乱码警告)雄踞史上最高赞之列。模式匹配和语法分析是两种工具。
  4. 性能恐惧要分场景。 小文本、可信输入上的回溯引擎完全够用,而且功能更强;真正危险的是「不可信输入 + 长文本 + 嵌套量词」三者叠加。因噎废食全线改用自动机引擎,会失去反向引用等能力,同样是过度反应。
  5. 方言差异被一笔带过。 视频用 JS 演示,但把同一模式抄进 Go 或 Python 前应重新验证语义与性能,这在多语言团队里尤其重要。

认知提升与实用启示

  1. 先问输入可信吗,再写正则。 处理用户提交、日志、爬虫内容等不可信文本时,优先选线性时间引擎(Go/Rust 标准库、RE2),或强制加超时与限制(.NET 的 Regex 支持 matchTimeout,PCRE2 有 match limit)。这一条习惯,价值超过一百条语法技巧。
  2. 可读性优先于炫技。 复杂模式拆成多条简单正则、开启 verbose 模式加注释、能用字符串方法解决就不上正则;超过三行的正则,考虑直接重写成代码。正则是压缩,不是密码学——六个月后你自己就是那个读不懂的人。
  3. 把调试工具变成肌肉记忆。 regex101.com 逐 token 解释并实时匹配,regexr.com 适合速查语法;测试永远要带一组「恶意样例」——长串重复字符喂给你的模式,看耗时曲线是不是平的。这十秒钟的验证,2019 年的 Cloudflare 用 27 分钟的宕机替全行业交了学费。

视频论证结构图

flowchart TD
  A["正则表达式<br/>文本匹配迷你语言"] --> B["语法层:四件套"]
  A --> C["理论层:正则语言"]
  B --> B1["字符类与量词"]
  B --> B2["锚点/分组/旗标"]
  C --> C1["Kleene 1956<br/>正则概念诞生"]
  C --> C2["Thompson 1968<br/>编译成机器码"]
  C1 --> D["两种引擎路线"]
  C2 --> D
  D --> E["回溯引擎<br/>PCRE/Python/JS"]
  D --> F["自动机引擎<br/>RE2/Rust/Go"]
  E --> G{"嵌套量词<br/>+不可信输入?"}
  G -->|"是"| H["灾难性回溯"]
  H --> I["ReDoS事故<br/>Cloudflare 2019"]
  G -->|"否"| J["正常匹配"]
  F --> K["线性时间保证"]

延伸阅读

  1. Russ Cox《Regular Expression Matching Can Be Simple and Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...)》(swtch.com/~rsc/regexp/regexp1.html)— 看懂回溯引擎与自动机引擎分野的必读长文
  2. Cloudflare 官方事后报告《Details of the Cloudflare outage on July 2, 2019》(blog.cloudflare.com)— 一条正则放倒全球网络的完整尸检报告

参考来源

  1. Fireship 视频检索入口(YouTube) — 视频本体(播放量等实时数据本次未能核实,发布前建议复核)
  2. Details of the Cloudflare outage on July 2, 2019 — Cloudflare Blog — 灾难性回溯事故的官方技术复盘
  3. Regular Expression Matching Can Be Simple and Fast — Russ Cox — 两种正则引擎技术路线的经典论述
  4. Stephen Kleene, Representation of Events in Nerve Nets and Automata (1956) — 「正则」概念的原始出处
  5. Ken Thompson, Programming Techniques: Regular Expression Search Algorithm, CACM (1968) — 正则编译与 grep 的技术源头

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入