正则表达式运算符优先级
正则表达式中的各种元字符和语法元素在解析时有严格的运算符优先级(从高到低)。优先级越高,越先被解析和匹配。这类似于数学表达式中的“先乘除后加减”。
掌握优先级非常重要,因为它直接影响正则的匹配行为。如果不了解优先级,容易写出意料之外的模式。
运算符优先级表(从高到低)
| 优先级 | 运算符/语法 | 描述 | 示例说明 |
|---|---|---|---|
| 1(最高) | () | 括号(捕获或非捕获分组) | (ab)+ 先将 “ab” 视为一个整体,再应用 + |
(?:) | 非捕获分组 | 同上,但不捕获 | |
(?=) (?!) (?<=) (?<!) | 零宽断言(前瞻、后瞻) | a(?=\d) 先看断言,再匹配 a | |
| 2 | * + ? {n} {n,} {n,m} | 量词(重复次数) | ab+ 先匹配 “b”,再重复 + |
*? +? ?? {n,m}? | 懒惰量词 | 同上,但为懒惰模式 | |
| 3 | ^^(序列连接) | 字符、字符集、子表达式的串联 | abc 等价于 a 然后 b 然后 c |
. \d \w [] [^^] 等 | 字符匹配、字符类 | ||
| 4 | | | 或(选择分支) | a|b|c 先匹配 a,或 b,或 c |
| 5(最低) | ^ $ \b \B 等 | 锚定(位置) | 只在整体模式开头/结尾生效 |
详细解释与示例
- 括号最高优先级
括号会改变默认的结合顺序。
示例:
cat|dogfood→ 匹配 “cat” 或 “dogfood”(| 优先级低,整个 “dogfood” 被视为一个分支)(cat|dog)food→ 匹配 “catfood” 或 “dogfood”(括号强制先处理 |)
- 量词紧随其后
量词只作用于紧邻前面的一个单元。
示例:
abc+→ “ab” 后跟一个或多个 “c”(abc)+→ 一个或多个 “abc”
- 序列连接优先于 |
示例:
apple|pie→ 匹配 “apple” 或 “pie”apple|piechart→ 匹配 “apple” 或 “piechart”(因为 “piechart” 是序列)- 要匹配 “apple” 或 “pie” 再加 “chart”:
(apple|pie)chart
- 常见误区示例
- 想匹配 “http” 或 “https” 开头的 URL:
错误:http|https://example.com→ 实际匹配 “http” 或 “s://example.com”
正确:https?://example.com或(http|https)://example.com - 想匹配 “abc” 或 “abd” 后跟数字:
正确:(abc|abd)\d+ - 贪婪与懒惰也受优先级影响:
<.*?>→ 先括号分组(但这里无括号),然后量词 .*?(懒惰)
记忆口诀
从高到低:
括号 > 量词 > 字符序列 > 或 > 锚定
即:
- 先看括号和断言
- 再处理重复(* + ? {})
- 然后是字符一个接一个
- 再考虑 | 分支
- 最后定位 ^ $ 等
建议
- 遇到复杂正则时,多用括号
( )明确分组,避免优先级陷阱。 - 在 regex101.com 等工具中调试,能清晰看到每个部分的匹配顺序。
理解了优先级,你写的正则就会更精准、可控!如果你有具体的正则想分析它的优先级解析过程,欢迎贴出来,我帮你拆解。