说明:本次会话联网工具受限,未能在线复核视频页实时数据;本文对该集内容的概述基于视频公开信息与系列惯例整理,播放量等实时数据以频道页面为准。文中涉及的技术史与安全事件均为公开可查证的资料,出处见文末参考来源。
正则表达式是程序员用得最多、却理解得最浅的工具之一:几乎人人会“抄”一段正则来校验邮箱、抓取日志,但很少有人真正明白,这段 /.../ 里的符号串到底是怎么“跑”起来的,以及为什么同一个模式在 A 系统里毫秒出结果、在 B 系统里能把 CPU 打满到服务瘫痪。
Fireship 频道的《Regular Expressions (Regex) in 100 Seconds》正是补齐“第一层认知”的经典单集:一百多秒的正片冲刺,把正则从“神秘天书”还原成“一门微型声明式语言”。本文在视频只讲“是什么”的地方,替你往下多挖三层——它从哪来(理论溯源)、它怎么执行(两种引擎)、它怎么闯祸(一场真实的大型事故)——让你看完等于看完了视频,还多懂一层。
| 项目 | 内容 |
|---|---|
| 视频标题 | Regular Expressions (Regex) in 100 Seconds(正则表达式100秒速成) |
| 频道 | Fireship(主讲:Jeff Delaney) |
| 频道定位 | 头部编程知识频道,以"…in 100 Seconds"高密度速成系列和行业快评著称 |
| 发布时间 | 约2021年(该系列高峰期单集;精确日期未能在线核验,以频道页为准) |
| 播放量 | 未能在线核验,实时数据以频道页面为准 |
| 本集定位 | 100秒系列的编程基础经典单集,长期被用作正则入门的“第一课” |
视频的叙事极快,但骨架清晰,按顺序其实是五件事。
第一件:正则不是“符号技巧”,而是一门语言。 视频开宗明义地把正则定义为“用模式描述文本”的声明式语言——你不写“先取第一个字符,再判断是不是数字”的过程代码,而是直接写出“我要的东西长什么样”。这是理解正则最重要的视角转换:从“怎么做”转向“是什么”。
第二件:五类积木拼出一切模式。 视频用连续的代码示例过了一遍正则的核心构件——字符类(如 [0-9]、\d 匹配一个数字)、任意字符 .、锚点(^ 开头、$ 结尾)、量词(* 零次以上、+ 一次以上、{2,4} 指定次数)、分组与捕获 ()。复杂如校验电话号码、抓取 HTML 标签的模式,都是这五类积木的组合。
第三件:它不挑宿主语言。 视频以 JavaScript 为示范宿主(match、replace、test),但刻意点明:正则语法几乎是跨语言通用的最小公约数,Python、Java、Go、编辑器的查找框里都认同一套写法。这让它成为程序员的“第二母语”——学一次,处处能用。
第四件:会用,不等于用好。 一百秒的正片当然讲不完善的艺术,但视频用邮箱校验这类经典例子暗示了正则的深坑:看起来人畜无害的一行模式,遇到“恶意构造”的输入可能完全失控。这层在视频里只是轻轻带过,却是本文要重点展开的“多懂一层”。
第五件:为什么值得每个工程师学。 视频的收尾立场很鲜明——在日志分析、数据清洗、搜索替换、词法解析这些场景里,正则的投入产出比极高;它不是炫技工具,而是工程师的日常杠杆。
视频没讲的来龙去脉,才是这条知识链真正精彩的部分。
1. 起源:1950年代,正则诞生于神经科学。 “正则表达式”的理论源头是数学家 Stephen Kleene 1956年的论文《Representation of Events in Nerve Nets and Automata》:他在研究麦卡洛克-皮茨神经网络的建模时,定义了一类可以用极简算子(连接、并、 Kleene 星号 *)描述的“正则事件”——这就是今天每个正则里那个 * 的名字来源。也就是说,正则最初描述的不是文本,而是神经网络的可达状态。
2. 工程化:1968年,Ken Thompson 把它变成了软件。 Thompson 在 CACM 发表《Regular Expression Search Algorithm》,首次把正则编译成 IBM 7094 的机器码来执行搜索,核心技术后来被称为“Thompson 构造法”——把正则展开成非确定性有限自动机(NFA)同时模拟所有可能路径,时间与文本长度成正比。他把这套实现带进了贝尔实验室的编辑器 ed,而 ed 里那条“全局搜索正则并打印”(g/re/p)的命令,后来独立成一个工具,就是沿用至今的 grep。1976年,Michael Rabin 与 Dana Scott 因有限自动机理论(包括 NFA 与 DFA 等价性,1959年论文)共同获图灵奖——正则的理论地基在七十年代就已浇筑完毕。
3. 分岔:Perl 与 PCRE 的“回溯时代”。 1987年 Larry Wall 发布 Perl,把正则扩展成带反向引用、环视等特性的“超集”——这些新特性破坏了纯自动机的线性时间保证,Perl 选择了递归回溯引擎:匹配失败就退一步换条路再试。Philip Hazel 开发的 PCRE(1997年起)继承了这套语义,被 PHP、Apache、无数编辑器采纳,也成了今天大多数语言标准库的默认行为。代价被埋进了地基里:回溯引擎的最坏时间复杂度是指数级的。
4. 警钟:2007年,Russ Cox 的著名长文。 Google 工程师 Russ Cox 发表系列文章《Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby)》,用实测数据证明:对同一批模式,基于 Thompson/NFA 模拟的引擎在恶意输入面前保持线性时间,而主流语言的回溯引擎会慢上千万倍;他随后主导了线性时间引擎 RE2 的实现(放弃反向引用作为代价),Google 自家的 Go 语言标准库 regexp 采用的正是 RE2 语义,Rust 的 regex crate、.NET 7 新增的 RegexOptions.NonBacktracking 都是同一条技术路线。V8 引擎(Chrome/Node.js)的 Irregexp 则走另一条路:保留回溯语义,但把正则即时编译成本地机器码来压低成本。
5. 事故:一条正则放倒半个互联网的基础设施。 2019年7月2日,Cloudflare 部署了一条内含嵌套量词的 WAF(Web应用防火墙)规则,其正则在特定输入上触发“灾难性回溯”(catastrophic backtracking)——回溯路径数随输入长度指数爆炸,全球机房的 CPU 被这一条正则吃满,大量请求返回 502,事故持续约27分钟(据 Cloudflare 官方复盘)。一个服务全球近半流量的网络,被一行“长得没问题”的正则拖垮。这类攻击有自己的名字:ReDoS(Regular Expression Denial of Service),已被 OWASP 收录为独立攻击类别。这也是为什么每份现代安全清单都要求:凡是处理用户输入的正则,必须限制输入长度、设置超时,或改用线性时间引擎(Python 可换 google-re2,Java 有 RE2J,Go 原生即安全)。
6. 一句流传四十年的忠告。 “有些人遇到问题,想‘我知道了,用正则吧’。于是他们有了两个问题。”这句话常被归于 Netscape 早期工程师 Jamie Zawinski 名下——它不是让你别用正则,而是提醒你:你引入的是一门语言加一个引擎,两者的坑你都得懂。
证据充分的部分: 视频对正则语法本身的演示(字符类、量词、锚点、分组)是教科书级无误的,语法语义在 ECMAScript、PCRE、POSIX 几大标准间高度一致;"正则是声明式语言”“跨语言通用”的定位也是社区共识。
被压缩或省略的部分(这是100秒体裁的必然代价):
\w、. 对多语言文本、组合字符、Emoji 的行为随引擎标志位而变,中文处理者尤其需要留意——这是面向英文示例的入门课共同的盲区。公道话: 作为100秒体裁,它完成了最难的任务——让初学者在两分钟内建立“模式即语言”的正确心智模型,而不是把正则当成一堆需要死记的咒语。深度的缺失是体裁属性,不是内容错误;缺的那一层,正是本文与 Russ Cox 系列文章存在的意义。
1. 给处理用户输入的正则做“安全体检”。 上线前问三个问题:输入长度有没有上限?这个引擎有没有超时或中断机制?量词是否嵌套(如 (a+)+、(a|a)* 这类结构是回溯爆炸的经典火药)?三条里有任何一条答不上来,就改用线性时间方案或加防护。
2. 用工具代替“瞪眼调试”。 regex101.com 能逐条解释模式、实时高亮匹配并单步回放引擎的回溯过程;开源工具 recheck 可以静态扫描你代码库里的正则,标记潜在 ReDoS 风险。与其背符号手册,不如把这两个工具焊进日常调试流程。
3. 记住引擎的“三句话模型”,比多背十个符号更值钱。 一、老牌引擎(Perl/PCRE 系)靠回溯,表达力强但最坏指数级;二、新派引擎(Go/RE2/Rust/.NET NonBacktracking)靠自动机模拟,恒定线性但砍掉反向引用;三、凡是能把模式写进“嵌套量词”结构的地方,就是事故预定的地方。用这三句话审视每一行正则,你就拥有了大多数工程师没有的“引擎视角”。
flowchart TD
A[一条正则被提交] --> B{引擎如何执行}
B -->|自动机模拟| C[Thompson构造<br/>线性时间]
B -->|递归回溯| D{量词是否嵌套}
D -->|否| E[常规输入可正常工作]
D -->|是| F[回溯路径指数爆炸<br/>CPU打满]
F --> G[真实事故<br/>Cloudflare约27分钟]
C --> H[工程对策<br/>RE2系引擎]
F --> H
H --> I[再加保险<br/>限长与超时]
这条视频只用了一百秒,但正则的故事横跨七十年:从 Kleene 笔下的神经网络事件,到 Thompson 的 7094 机器码,到 Perl 的回溯分岔,再到 Cloudflare 机房里那27分钟的 CPU 风暴。看懂这条线,你就不会再把正则当作“会抄就行”的咒语——你抄下去的每一行,都是一门有引擎、有代价、有脾气的小语言。下次写 /(a+)+$/ 之前,你会想起机房里那台风扇狂转的服务器。
本文由「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 等场景全覆盖。
