正则分支匹配“|”是左到右短路逻辑或,成功即止;长模式需前置,括号限定作用域,修饰符可局部生效,findall/finditer用于获取全部匹配。
正则表达式里的分支匹配(用 | 表示)本质就是逻辑“或”,但它不是并行判断,而是**从左到右依次尝试、一旦成功就停止**——这就是所谓的“逻辑短路”。它不回溯去试其他分支,除非当前分支彻底失败。
短路行为直接影响匹配结果
比如模式 r"cat|catalog" 去匹配字符串 "catalog",结果只会匹配到 "cat",而不是更长的 "catalog"。因为引擎先试 "cat",发现开头能对上,就直接返回,根本不会继续看后面的 "catalog"。
- 短路是默认行为,不可关闭;它不是 bug,而是设计机制
- 匹配顺序决定结果:长模式必须放在前面,才能避免被短模式截断
- 写成
r"catalog|cat"就能正确匹配完整单词
括号是控制短路范围的关键
没有括号时,| 的作用范围容易被误解。例如 r"^ab|cd$" 实际匹配的是 “以 ab 开头” 或 “以 cd 结尾”,而不是 “ab 或 cd” 整体出现在行中。
- 想匹配整词“ab”或“cd”,必须加括号:
r"^(ab|cd)$" - 分组不仅限定作用域,还支持捕获和命名,便于后续区分来源
- 非捕获组
(?:...)适合仅需逻辑分组、不需提取内容的场景
短路与修饰符可以局部配合
修饰符如 (?i)(忽略大小写)、(?s)(点号跨行)可作用于单一分支,实现精细控制。
-
r"(?i)http|https"等价于r"(?i)https?",但写法更直观 -
r"(?i)the (?-i)cat"表示 “the” 不区分大小写,“cat” 必须小写 - 这种嵌套写法让不同分支拥有独立行为,避免全局修饰带来的副作用
获取全部可能匹配要绕过短路限制
re.search() 只返回第一个成功分支的结果;如果想找出所有符合任一分支的片段,得用 re.findall() 或 re.finditer()。
-
re.findall(r"dog|cat|bird", text)返回所有出现的单词列表 - 若需知道每个匹配来自哪个分支,可用命名组:
r"(?P<animal>dog)|(?P<food>apple)"</food></animal> - 遍历
finditer结果时,通过match.groupdict()查看哪一组有值

















