分支是择一
竖线把模式分成若干分支,匹配时按从左到右的顺序逐个尝试,第一个能走通的分支就被采用,其余分支不再尝试。这与「取最长」无关,所以分支的书写顺序会直接影响结果,而不是只影响可读性。
优先级最低
竖线的作用范围覆盖它左右两侧直到最近的分组边界或模式两端,优先级低于量词与连接。想把或逻辑限定在局部,必须用圆括号把分支范围括起来,否则整条模式会被意外拆成两个完全不同的分支。
基本信息
| 语法 | 竖线分隔多个备选分支 |
|---|---|
| 选择策略 | 从左到右,先成功者胜,不做最长优先 |
| 优先级 | 低于量词与连接,高于分组之外的一切边界 |
| 分组影响 | 分支写在括号内时只影响括号范围 |
| 分支长度 | 各分支长度可以不同,与字符类要求等长不同 |
| 引擎差异 | 部分引擎会对分支做前缀优化,但语义仍是先成功者胜 |
典型使用场景
- 匹配多种可接受的日期分隔符或单位后缀
- 同时接受多个文件扩展名,例如图片与压缩包
- 匹配多种日志级别关键字,注意把更长的关键字写在前面
- 在括号内限定备选范围,避免竖线影响整条模式
- 合并多条相似规则为一条模式,减少重复
顺序与范围的影响
顺序与范围的影响
import re
re.search(r'a|ab', 'ab').group(0) # 先试左分支,只拿到 a
re.search(r'ab|a', 'ab').group(0) # 更具体的分支写在前面才拿到 ab
re.search(r'cat|dog', 'hotdog').group(0) # 分支可以出现在串内任意位置
re.fullmatch(r'(jpg|jpeg|png)', 'jpeg') # 括号限定范围后做整串校验
re.fullmatch(r'jpg|jpeg|png', 'jpeg') # 没加括号:整条模式被拆成三个分支
re.findall(r'INFO|WARN|ERROR', 'INFO ERROR WARN') # 多关键字提取分支写法对照
| 需求 | 写法 | 注意点 |
|---|---|---|
| 多个固定字符串 | 竖线分隔各串 | 长关键字写在短关键字之前 |
| 局部择一 | 括号包裹分支 | 否则整条模式被拆分 |
| 可重复的择一 | 括号包裹后再加量词 | 量词只作用于紧邻元素 |
| 与字符类比较 | 等长单字符用字符类 | 字符类更短且更快 |
分支顺序问题最典型的例子是同时匹配短关键字与长关键字:短的写在前面,长的永远匹配不上。把更具体、更长的分支前置,是比较省心的习惯。
如果各分支只是单字符的差异,用字符类代替分支更清楚也更快。分支的价值在于各分支长度或结构不同,字符类做不到时才使用。