模式:一门微型语言
正则表达式(regex)描述一组字符串。不必枚举每一种可能,你只需写出模式:「三位数字」「类似电子邮件的形状」「以 ERROR 开头的行」。编程语言、编辑器和数据处理工具内嵌 regex 引擎,便于搜索、校验与提取文本。
Regex 方言各不相同(JavaScript、Python、PCRE、Rust)。本指南聚焦多数现代引擎的共通概念,并偏向浏览器中常见的 JavaScript 风格语法。可用 正则测试工具 交互式试验模式。
字面量与元字符
多数字符匹配自身:cat 按顺序匹配三个字母 c-a-t。元字符带有特殊含义:. ^ $ * + ? ( ) [ ] { } \ |(具体还取决于方言)。
若要字面匹配某个元字符,用反斜杠转义:\. 匹配一个句点。在某些语言里,字符串转义会叠在 regex 转义之上——造成「反斜杠地狱」。语言若提供原始字符串(raw string),优先使用。
字符类
方括号列出允许的字符:[abc] 匹配 a、b 或 c。[0-9] 这类范围匹配数字。否定 [^0-9] 匹配非数字字符。
简写类(随 flavor 而异)包括 \d(数字)、\w(单词字符)、\s(空白)。精确定义并不统一——尤其涉及 Unicode 时。校验必须精确时,优先用显式范围,或在引擎支持时使用 Unicode 属性转义(现代 JS 中 \p{L} 表示字母)。
锚点
^ 匹配字符串开头(多行模式下也可匹配行首)。$ 匹配结尾。\b 匹配单词边界。锚点不消耗字符,只断言位置。
在尊重锚点时,^\d{5}$ 匹配恰好五位数字的字符串——而不是埋在更长文本中的五位数字。
量词
量词指定重复次数:
| 量词 | 含义 |
|---|---|
* | 零次或更多 |
+ | 一次或更多 |
? | 零次或一次 |
{n} | 恰好 n 次 |
{n,} | n 次或更多 |
{n,m} | n 到 m 次(含) |
默认量词是贪婪(greedy)的:在整体模式仍能成功的前提下尽可能多匹配。惰性变体(*?、+?)尽可能少匹配。贪婪匹配常导致「我的模式把整份文档都吞了」这类意外。
分组与分支
圆括号 ( ... ) 创建分组,用于量化子模式并捕获子串。(ab)+ 匹配 ab、abab 等。分支 | 在选项间选择:cat|dog。
非捕获分组 (?: ... ) 只做结构分组、不保存捕获——当你只需结构时更干净。
许多引擎支持命名捕获((?<year>\d{4})),提取时可读性更好。
贪婪陷阱与回溯
对某些输入,经典危险模式形如 (.*)+ 或嵌套的歧义量词。病态回溯可能拖死进程——即 ReDoS(regular expression denial of service)。生产环境若接受用户提供的模式,应使用超时、安全子集解析器,或具备线性时间保证的引擎。编写自有模式时,尽可能用具体字符类取代 .*。
标志 / 修饰符
常见标志:
i— 忽略大小写m—^/$按行生效s— 点号匹配换行(在支持该能力的引擎中)g— 查找全部匹配(global)u— JavaScript 中的 Unicode 模式
标志会大幅改变语义;务必记录校验器使用了哪些标志。
校验与提取
校验关心整个输入是否匹配:常把模式与起止锚点配对,或使用隐含「全量匹配」语义的 API。 提取寻找子串:使用搜索/全局 API 与捕获组。
不要把松散的电子邮件 regex 当成完整的 RFC 校验器。对关键格式,应把 regex 与专用解析器结合。
小型学习阶梯
- 匹配固定单词。
- 为数字加入字符类。
- 用
{n}量化数字。 - 锚定模式。
- 引入一个可选分组。
- 提取一个捕获。
- 若引擎支持,再尝试先行断言 / 后行断言(lookahead / lookbehind)。
直接复制网上「完美电子邮件正则」几乎学不到东西,边缘情况也常失败。
测试习惯
- 维护一张「应匹配 / 不应匹配」示例表。
- 覆盖空字符串、最大长度与 Unicode 样本。
- 在
m或「点号跨换行」重要时,测试多行输入。 - 调试时先简化模式,直到意外匹配消失,再逐步重建。
测试模式工具 可在把模式硬编码进应用代码之前,帮你用示例反复迭代。
可读性与维护
过长的正则往往「写一次、再也不敢读」。策略:
- 把校验拆成多个小检查。
- 若可用,使用详细/扩展模式(Python
re.X)并加注释。 - 把模式赋给具名常量。
- 对嵌套结构(HTML、JSON)优先用解析器——对任意嵌套深度,regex 是错误工具。
先行 / 后行断言(可选下一步)
熟悉锚点与分组后,许多引擎提供 lookahead 与 lookbehind:在不消耗字符的前提下,断言某位置之后或之前的内容。例如,正向前瞻可要求类密码字符串某处包含数字,而不必别扭地移动主匹配游标。这些特性强大却易被滥用;应少用、加注释,并在你的确切方言中验证行为——lookbehind 支持与定宽规则并非处处相同。
小结
正则表达式用字面量、字符类、量词、锚点与分组描述文本形状。当模式具体且经过测试时,它们擅长简洁校验与提取。注意方言差异,避免灾难性回溯,并在语法复杂度超出一行标点时升级到真正的解析器。