“找个邮箱正则” 大概是程序员搜索次数最多的需求之一,但网上随手抄的那条,十有八九要么漏匹配、要么把非法值放进来。问题不在正则语法,而在于:每条”常用正则”背后都有一条隐形的边界线——正则能管到哪、从哪开始必须交给程序。这篇把 Regex Pro 内置示例栏里的 13 条逐个拆开,给你能跑的 pattern + 它的覆盖边界 + 那条”到此为止”的线。
邮箱:别追求 RFC 完美,要”足够好”
Pattern: [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}
Flags: i
完整符合 RFC 5322 的邮箱正则有几百字符,还覆盖现实中根本不出现的形式(带引号的本地名、IP 字面域名)。工程上用上面这条就够:本地名允许 字母数字 . _ % + -,域名允许 字母数字 . -,顶级域至少两位字母。
| 能匹配 | 故意不匹配 |
|---|---|
a.b+tag@sub.example.com | "a b"@x.com(带引号本地名) |
user_01@mail.co | a@[192.168.0.1](IP 字面域) |
那条线:正则只能判断”长得像邮箱”。判断邮箱真实存在,只能靠发一封验证邮件——别指望正则替你拦掉填错的地址。
手机号:锚定比号段更重要
Pattern: (?<![0-9])1[3-9]\d{9}(?![0-9])
中国大陆手机号就是 1 开头、第二位 3–9、共 11 位。不要硬编码号段(13x、145、166、198……)——号段由工信部不定期放号,写死等于给自己挖”明年漏匹配”的坑。
真正该补的是边界:裸写 1[3-9]\d{9} 会从 手机13800138000转8001 里抠出子串。前后加否定断言 (?<![0-9])…(?![0-9]),挡住”两端还粘着数字”的脏串。
身份证:正则只管格式,校验码归代码
Pattern: [1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]
18 位二代证结构:地址码(6) + 年(4) + 月(2) + 日(2) + 顺序码(3) + 校验码(1)。正则能挡位数、月份 13、日期 32。
但两件事正则做不到:
- 最后一位校验码是前 17 位按 ISO 7064 MOD 11-2 加权求和取模算出来的——正则不能做模运算,必须用代码补。这是”格式过了却是假号”最常见的漏洞。
- 2 月 30 日这种”月份合法但该月没这天”——闰年逻辑写不进正则,得靠
Date解析。
实名 / 法务场景尤其注意:格式通过 ≠ 号码有效。正则做粗筛,校验码和真实日期必须程序兜底。
URL 与 IPv4:放行非法值的重灾区
IPv4 新手坑——\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} 会放行 999.999.999.999。每段 0–255 的正确写法:
单段: (?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)
整条: (?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}
25[0-5] 管 250–255、2[0-4]\d 管 200–249、1\d\d 管 100–199、[1-9]?\d 管 0–99。把这条贴进 Regex Pro,开「解释」面板能看到它逐段翻译,一眼确认范围。
URL 实用版(不追求覆盖 ftp / userinfo / IDN):
https?://[\w.-]+(?:\:\d+)?(?:/[\w./?%&=#-]*)?
http/https + 域名 + 可选端口 + 可选路径查询。需要更多协议或国际化域名时再按需扩展,别一上来就写一条没人看得懂的”全能 URL 正则”。
其余示例速览
| 示例 | pattern 要点 | 边界提醒 |
|---|---|---|
| UUID | [0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12} | 第 13 位是版本号、第 17 位是变体位,写死能挡乱造的 UUID |
| 日期 | `\d{4}-(?:0[1-9] | 1[0-2])-(?:0[1-9] |
| HEX 颜色 | `#(?:[0-9a-fA-F]{3} | [0-9a-fA-F]{6})` |
| SemVer | \d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)? | 预发布 -rc.1 与构建元数据 +build 可选 |
| 强密码 | (?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,} | 全靠先行断言堆条件,加 (?=.*[^\w]) 要求符号 |
| HTML 标签 | <(?<tag>[a-z]+\d*)[^>]*> | 提取标签名用,别真用正则解析整个 HTML |
| 中文姓名 | [一-龥]{2,4} | 常用汉字区间,复姓 / 少数民族长名要放宽上限 |
从工具到代码:别让格式通过等于业务通过
调好 pattern 后,三步落地:
- 贴真实脏数据复测——干净样本人人能过,坑都在边界。
- 「单元测试」标签固化用例——“应匹配 / 不应匹配”两类都加,pattern 一改即回归。
- ⎘ JS / ⎘ Py / ⎘ Java 导出——工具自动处理目标语言的转义。
最后再强调一次那条贯穿全篇的线:邮箱真实存在、身份证校验码、IPv4 可达性、日期真实性——正则一概管不了。 Regex Pro 帮你把”长得对不对”调到位,剩下的逻辑兜底,留给代码。