每个开发者都该收藏的常用正则表达式模式

深色编辑器背景上展示常用正则表达式模式参考,包含高亮显示的模式匹配语法代码

正则表达式(regex)是一种可复用的模式模板,用于匹配文本中特定的字符序列 - 你可以把它理解成一个超强的"查找"工具,几乎适用于所有主流编程语言。无论是验证邮箱地址、从表单中提取手机号,还是解析日志文件,掌握几个常用的正则表达式就能搞定 90% 的需求。本文整理了最实用的正则模式,逐一解释每个部分的作用,并教你如何灵活改写。

正则语法速查

在介绍各类模式之前,先来看一张常用语法元素速查表。即使你之前用过正则表达式,把这些基础元素放在一起查阅也非常方便。

元字符 含义 匹配示例
. 匹配除换行符以外的任意字符 a.c 可匹配 abc a1c
\d 任意数字(0-9) \d\d 可匹配 42
\w 单词字符(字母、数字、下划线) \w+ 可匹配 hello_world
\s 空白字符(空格、制表符、换行符) \s+ 可匹配多个连续空格
^ / $ 字符串的开头 / 结尾 ^\d+$ 仅匹配 123
{n,m} 重复 n 到 m 次 \d{2,4} 可匹配 12 1234
[abc] 字符类 - 匹配 a、b、c 中的任意一个 [aeiou] 可匹配任意元音字母
(?:...) 非捕获分组 分组但不保存反向引用
(?=...) 正向前瞻 断言后续内容,但不消耗字符

MDN Web Docs 正则表达式指南 是学习 JavaScript 正则语法最好的参考资料,下面大多数模式也可以直接用于 Python、PHP、Java 和 Ruby,只需根据各语言的标志位稍作调整即可。

邮箱验证

邮箱验证是正则表达式最经典的使用场景,也是很多开发者容易写过头的地方。 RFC 5322 规范 理论上允许 "very unusual"@example.com 这样的地址格式,但几乎没有正则能完整覆盖。对于 99% 的实际表单验证场景,用下面这个务实的模式就够了:

^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$

各部分说明:

  • [a-zA-Z0-9._%+\-]+ - 本地部分(@ 之前);允许点号、加号、连字符、下划线
  • @ - 字面量 @ 符号
  • [a-zA-Z0-9.\-]+ - 域名,包含子域名
  • \.[a-zA-Z]{2,} - 至少 2 个字符的顶级域名(如 .io、.com、.museum)
正则表达式本身无法确认邮箱地址是否真实存在或可正常收信。对于任何重要场景,都应发送确认邮件来完成验证。

URL 与网址匹配

URL 模式匹配的应用场景很广,从从纯文本中提取链接,到验证用户填写的网址字段,都能用到。

https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)
  • https? - 同时匹配 http https
  • (?:www\.)? - 可选的 www 前缀
  • [-a-zA-Z0-9@:%._+~#=]{1,256} - 主机名字符,最多 256 个字符
  • \.[a-zA-Z0-9()]{1,6} - 顶级域名
  • \b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*) - 可选的路径、查询字符串和片段标识符

如果只需要验证而不需要提取,可以在模式前后加上 ^ $ 锚点。

手机号与电话号码

电话号码的格式因国家和用户习惯差异极大,处理起来比较麻烦。下面两个模式可以覆盖大多数常见场景:

美国/加拿大(NANP)格式

^(\+1[-.\s]?)?(\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}$

可匹配: 555-867-5309 (555) 867 5309 +1.555.867.5309 5558675309

国际格式(E.164)

^\+[1-9]\d{6,14}$

E.164 是大多数电话 API(如 Twilio、AWS SNS)所使用的格式,以 + 加国家代码开头,不含空格或标点符号。

如果需要超出基本格式检查的功能,比如验证某个号码在特定国家是否为有效的手机号,建议使用专用库 libphonenumber (Google 开源的电话号码处理库,支持 Java、JavaScript、Python 等多种语言)。

日期与时间

日期模式匹配在日志解析、表单验证和数据管道中非常常见。具体使用哪种格式,取决于你的数据来源。

ISO 8601 格式(YYYY-MM-DD)

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

美式格式(MM/DD/YYYY)

^(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])\/\d{4}$

24 小时制时间(HH:MM 或 HH:MM:SS)

^([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?$

注意,这些模式只验证格式,不验证日历逻辑。例如 2024-02-31 (2月31日并不存在)也会被接受。如需严格验证日期合法性,请在正则检查之后再用语言内置的日期库进行解析。

密码强度验证

密码规则通常要求包含多种字符类型并满足最低长度。使用前瞻断言可以将这些规则写在一个模式里,无需拆分成多次检查。

最少 8 位,包含至少一个大写字母、一个小写字母、一个数字

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$

强密码:8 位以上,包含大写字母、小写字母、数字和特殊字符

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$

每个 (?=.*[...]) 都是一个前瞻断言,用于扫描整个字符串,确保至少包含一个符合条件的字符。最后的 .{8,} 用于限制最低长度。你可以将 {8,} 替换为 {12,} 来要求最少 12 位,这也符合 NIST SP 800-63B 密码指南 的建议。

IP 地址匹配

IPv4

^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$

该模式通过明确匹配每个八位组(octet)的 0-255 范围,能正确拒绝 999.0.0.1 这类无效值。

IPv6(简化版)

^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$

该模式处理完整的 8 组格式。对于压缩表示法(例如用 ::1 表示回环地址),正则会变得相当复杂,此时使用网络库来解析比正则更可靠。

HTML 与标记语言

在这个场景下,有几个针对性的正则模式确实很实用。"不要用正则解析 HTML"这条原则对完整文档仍然成立 - 完整的 HTML 文档请使用 BeautifulSoup 或 DOMParser 这类专业 DOM 解析器。但对于特定的、范围明确的任务,正则完全可以胜任。

去除所有 HTML 标签

<[^>]*>

提取特定标签的内容(例如 <title>)

([^<]*)<\/title>

第 1 个捕获分组包含标题文本内容。

匹配 HTML 十六进制颜色值

#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\b

同时匹配 3 位简写形式( #fff )和 6 位完整形式( #ffffff )。

常用工具型正则

以下这些模式在各类项目中频繁出现,非常值得收藏。

Slug(URL 友好字符串)

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

可匹配 my-blog-post-2024 这样的字符串。不含大写字母,不以连字符开头或结尾,不包含连续连字符。

信用卡号(基本格式,不含空格)

^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$
  • 4 开头 - Visa(13 或 16 位)
  • 51-55 开头 - Mastercard(16 位)
  • 34 37 开头 - Amex(15 位)
  • 6011 65 开头 - Discover(16 位)
切勿存储原始卡号。此模式仅用于客户端的格式提示反馈。真正的卡号验证必须通过符合 PCI 合规标准的支付处理商(如 Stripe 或 Braintree)来完成。

空白字符规范化(合并多余空格)

\s{2,}

将匹配到的内容替换为单个空格,用于清理用户输入或爬取文本中的多余空白。

仅匹配数字

^\d+$

仅匹配字母和数字

^[a-zA-Z0-9]+$

匹配包含某个单词的行(配合标志位实现大小写不敏感)

^.*\bword\b.*$

单词边界 \b 可以防止在 password 这类单词内部误匹配 word

提取版本号(semver 格式)

\bv?(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.]+))?(?:\+([a-zA-Z0-9.]+))?\b

可从 v2.14.0-beta.1+build.42 这样的字符串中捕获主版本号、次版本号、修订号、预发布标签和构建元数据。

标志位与实用技巧

正则表达式的行为会因所使用的标志位不同而有所差异。以下是最常用的几个:

标志位 JS Python 效果
大小写不敏感 i re.IGNORECASE 大写和小写字母视为相同
全局匹配(查找所有) g re.findall() 返回所有匹配结果,而不仅是第一个
多行模式 m re.MULTILINE ^ $ 匹配每行的行首/行尾,而不是整个字符串的开头/结尾
点号全匹配(dotall) s re.DOTALL . 也能匹配换行符

几个能帮你节省大量调试时间的好习惯:

  • 始终用边界情况测试 - 空字符串、最大长度、Unicode 字符,以及那些"看起来合法但其实不合法"的输入。
  • 不需要捕获内容时,使用非捕获分组 (?:...) - 比捕获分组更快,代码也更清晰。
  • 验证模式一定要加锚点 ,使用 ^ $ ,防止无效字符串中的合法子串"蒙混过关"。
  • 警惕灾难性回溯 - 像 (a+)+ 这样的嵌套量词,在精心构造的输入下可能导致正则引擎卡死。量词应尽量保持简单和具体。
  • 编写正则时使用在线调试工具 regex101.com 提供实时匹配分析,能解释每个语法元素的含义,并支持在 PCRE、JavaScript、Python 等多种引擎之间切换。
正则表达式模式匹配与输入验证工具

告别猜测,轻松测试和验证正则表达式

有了合适的工具,编写可靠的正则验证模式会快得多。探索我们的免费开发者工具,使用正则表达式对文本进行清洗、检查和转换。

立即体验免费工具 →

贪婪量词(如 .* )会尽可能多地匹配字符,然后再回溯。懒惰量词(如 .*? )则尽可能少地匹配字符。例如,对于字符串 bold ,模式 <.*> 会匹配整个字符串,而 <.*?> 只会匹配 。在提取分隔符之间的内容时,使用懒惰量词更合适。

大体一致,但存在一些差异。Python 的 re 模块使用 PCRE 风格语法,支持 (?P...) 形式的命名分组。JavaScript 的标志位语法略有不同,旧版引擎(ES2018 之前)不支持后向断言。如果需要跨语言兼容,建议只使用通用子集:字符类、量词、锚点和基本分组。

用正则做格式验证在生产环境中完全没问题,几乎所有 Web 框架都在这样做。真正的风险在于写得不好的模式可能引发 ReDoS(正则拒绝服务)攻击,即通过触发灾难性回溯来耗尽资源。避免使用嵌套量词,让模式尽量具体,并在正则运行之前就限制合理的输入长度。

在大多数常见引擎中,对于 ASCII 输入两者是等价的。区别在于 Unicode 场景下:在某些引擎(如开启 Unicode 模式的 Python 3)中, \d 会匹配其他文字系统的数字,例如阿拉伯-印度数字。如果你明确只想匹配 ASCII 数字 0-9,使用 [0-9] 更严谨。对于大多数 Web 表单验证来说,这个区别通常不影响实际使用。

你需要两样东西:dotall 标志位(让 . 也能匹配换行符),以及可能还需要多行标志位(让 ^ $ 锚定到每一行,而不是整个字符串的首尾)。在 JavaScript 中使用 /pattern/ms ;在 Python 中组合使用 re.DOTALL | re.MULTILINE 。如果不开启 dotall, . 会在换行处停止,模式就无法跨行匹配。