返回博客
Reference 2026-04-25

2026年正则表达式速查表

正则表达式模式、标志和测试示例的快速参考。

正则表达式的语法密度之高,连每周都在用的人也会忘记细节。这份速查表涵盖你日常伸手就用的结构,加上2026年时代的新增内容——Unicode属性转义和 v 标志——以及那个能让生产服务瘫痪的性能陷阱。

字符类

  • \d / \D — 数字 / 非数字
  • \w / \W — 单词字符(字母、数字、下划线) / 其余一切
  • \s / \S — 空白 / 非空白
  • . — 除换行外的任意字符 (加 s 标志则包含换行)
  • [abc], [a-z], [^abc] — 集合、范围、取反集合
  • \p{L}, \p{Script=Han} — Unicode属性转义(需要 uv 标志)。\w 仅限ASCII,匹配国际文本请用 \p{L}

量词

  • ? — 零个或一个
  • + — 一个或多个
  • {n}, {n,}, {n,m} — 精确、至少、有界的次数
  • a* — 零个或多个a
  • 默认贪婪:量词会在保证模式其余部分仍能成功的前提下取最长匹配
  • 追加 ? 得到惰性版本 — +? 取最短匹配;经典用法是 <.+?>,匹配单个标签而不是一整行标签

锚点与边界

  • ^$ — 字符串的开头和结尾;配合 m 标志则是每一行的开头和结尾
  • \b / \B — 单词边界 / 非边界;\bcat\b 匹配「cat」但不匹配「category」
  • 边界的定义跟随 \w,因此默认同样仅限ASCII

分组与反向引用

  • (abc) — 捕获组,从左到右编号
  • (?:abc) — 非捕获组;纯分组时用它来保持编号稳定并节省分配
  • (?<name>abc) — 命名捕获,通过 match.groups.name 读取
  • \1\k<name> — 反向引用;(["'])(.?)\1 可匹配任一种引号包裹的字符串

环视

  • (?=x) / (?!x) — 肯定 / 否定先行断言
  • (?<=x) / (?<!x) — 肯定 / 否定后行断言 (JavaScript自ES2018起支持)
  • 环视不消耗字符,因此非常适合密码规则和插入位置匹配,例如千位分隔符: /\B(?=(\d{3})+(?!\d))/g

标志

  • g — 所有匹配而非仅第一个;与 exec 联用时有状态,是交替匹配bug的经典来源
  • i — 忽略大小写
  • m^$ 在换行处也匹配
  • s — 点号匹配换行
  • u — 正确的Unicode:星光平面字符算一个单位,启用属性转义
  • v (ES2024) — 包含 u 的一切,外加 [\p{L}--[aeiou]](除元音外的字母)这样的集合运算和 \p{RGI_Emoji} 这样的字符串属性
  • y — 粘性匹配,只在 lastIndex 处匹配;手写词法分析器的基石

久经考验的模式

邮箱(务实版):       ^[\w.+-]+@[\w-]+\.[\w.-]+$

IPv4逐段精确: ^(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)$

ISO 8601日期: ^\d{4}-\d{2}-\d{2}$

UUID v4: ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

URL slug: ^[a-z0-9]+(?:-[a-z0-9]+)*$

Hex颜色: ^#(?:[0-9a-fA-F]{3}){1,2}$

邮箱模式是刻意宽松的。完全符合RFC 5321的模式极其庞大,而且仍然无法告诉你邮箱是否存在——格式宽松校验,然后靠发送邮件来确认。

灾难性回溯

唯一会引发生产事故的正则行为。重叠备选分支上的嵌套量词——形如 (a+)+b(\w|\d)+$ ——会在长输入几乎匹配却在末尾失败时,迫使回溯引擎尝试指数级数量的切分方式。一个40字符的恶意字符串就能把一个CPU核心钉死几分钟;这就是ReDoS。

防御手段:

  • 让备选分支互不重叠,避免对已被量词修饰的组再加量词
  • 优先使用明确的字符类而不是 .
  • 线性时间引擎(RE2、Rust的regex库)在结构上免疫——代价是不支持反向引用和环视
  • 永远不要在请求线程上用用户提供的模式去匹配用户提供的输入;必须这样做时,放到worker里并设置超时

值得养成的习惯

  • 编译一次,重复使用:热循环中的正则字面量在某些引擎里会重建状态
  • 只要位置已知就加锚点 — ^ 让不匹配立即失败而不是扫描全文
  • 复杂模式用命名的源字符串组合起来,等于自带注释
  • 用对抗性输入测试:空字符串、超长的近似匹配、ASCII之外的Unicode

引擎的差异比语法更大

同一个模式在不同引擎上可能表现不同,知道自己站在哪个家族上能避免微妙的移植bug:

  • 回溯引擎 — JavaScript(V8的Irregexp)、PCRE2、Python的re、Java的java.util.regex。功能齐全,最坏情况指数时间。
  • 线性时间引擎 — RE2(Go的regexp使用)、Rust的regex库。通过自动机保证O(n)匹配;不支持反向引用和环视。
  • 混合型 — .NET提供NonBacktracking模式;PCRE2带有DFA匹配函数。

从Stack Overflow复制模式前要核对的功能差异:后行断言(Safari 16.4之前不支持,Go/RE2没有)、占有量词和原子组(仅PCRE和Java——JavaScript用先行断言加反向引用的技巧模拟),以及 \p 属性转义的覆盖范围。具体到JavaScript,遍历全局匹配请优先用matchAll——它绕开了让exec循环变脆弱的共享lastIndex状态;还要记住传入普通字符串的String.replace只替换第一处,你需要带g标志的正则。

在 sdk.is/regex-tester 的正则测试器中带匹配高亮实时打磨你的模式。