优先级顺序
正则的优先级从高到低大致是:转义与分组构造、量词、连接、分支。也就是说量词先绑定它前面的元素,连接把相邻元素串起来,竖线最后才把左右两侧切成备选分支。
低优先级带来的意外
因为竖线优先级最低,它会一路吞到最近的括号边界或模式两端,所以两侧的锚点、字符类、量词都可能被拉进各自的分支里。凡是想让分支只作用于局部,就必须显式加括号。
基本信息
| 优先级顺序 | 分组构造高于量词,量词高于连接,连接高于分支 |
|---|---|
| 分支作用范围 | 从最近的括号边界或模式两端到下一处竖线 |
| 常见后果 | 锚点被拆进单个分支,校验范围与预期不符 |
| 括号作用 | 圆括号可任意改变优先级与作用范围 |
| 可读性建议 | 即使优先级已符合预期,也建议显式加括号表达意图 |
| 引擎差异 | 各引擎优先级规则一致,差异主要出现在扩展构造的解析上 |
典型使用场景
- 写多分支校验时确认锚点覆盖全部分支而不是其中一支
- 把量词限定在正确的元素上,避免绑错对象
- 读陌生模式时按优先级拆解,判断竖线的实际作用范围
- 重构模式时通过加括号明确结构,减少歧义
- 排查「只有某些输入能通过校验」的问题,检查锚点落在哪一支
优先级造成的语义差别
优先级造成的语义差别
^a|b$ 等价于 (^a)|(b$):两处锚点分别属于不同分支
^(a|b)$ 锚点包住整组,整个字符串只能是一个字符
ab|cd 等价于 (ab)|(cd):连接优先于分支
ab* 等价于 a(b*):量词只作用于 b,不作用于 ab
(ab)* 量词作用于整组
^\d{4}-\d{2}$ 量词作用于紧邻的字符类,锚点在两端
^(0|[1-9]\d*)$ 分支写在括号内,锚点才覆盖整个结构表达式等价拆解
| 写法 | 等价形式 | 说明 |
|---|---|---|
| 脱字符加 a 竖线 b 加美元符号 | 两支各带一处锚点 | 锚点不覆盖整条模式 |
| a 竖线 b 加美元符号 | 两支各带一处锚点 | 常见校验漏洞来源 |
| a 加 b 加星号 | 量词只绑定 b | 连接不参与量词绑定 |
| 括号内 a 竖线 b 加星号 | 量词作用于整组 | 需要重复多分支时用此写法 |
校验类模式尤其要把锚点与分支的括号关系写清楚。只要有一处分支没被锚点覆盖,非法输入就能从那一支溜过去。
显式加括号不会改变语义,却能显著降低阅读成本。评审模式时如果必须停下来算优先级,加括号是更省事的做法。