分组解决两件事
圆括号把若干元素打包成一个整体,一是让量词可以作用于整组而不是单个字符,二是把命中内容单独记下来方便提取或引用。前者改变匹配语义,后者只影响结果如何被读出。
捕获的代价
每个捕获组都会让引擎额外记录起止位置,数量多时会增加开销,也会让组编号变得难读。只看结构不取内容的分组,应当改用非捕获写法,既省开销也不打乱编号。
基本信息
| 语法 | 圆括号包裹要分组的元素 |
|---|---|
| 编号起点 | 第 1 组是第一个左括号,第 0 组固定表示整个匹配 |
| 作用一 | 让量词作用于整组,如整组重复若干次 |
| 作用二 | 把匹配片段取出,用于替换或后续处理 |
| 未参与匹配 | 可选分支未命中时该组内容为空,需要区分空串与未参与 |
| 替代写法 | 非捕获分组只分组不记录,命名分组便于按名字读取 |
典型使用场景
- 提取结构化字段:从日期、地址、日志行里分别取出各段
- 把量词作用到多字符结构上,实现整组重复
- 限定分支范围,让或运算只在组内生效
- 替换时引用组内容重排文本,例如把日期改写成另一种顺序
- 校验并同时抽出关键片段,避免写两条模式
分组的两种用途
分组的两种用途
import re
m = re.search(r'(\d{4})-(\d{2})', '2026-10')
print(m.group(0)) # 整个匹配内容
print(m.group(1)) # 第一个括号里的内容
print(m.groups()) # 全部捕获组成元组
re.search(r'(ab){2}', 'abab') # 量词作用于整组,必须匹配两遍
re.sub(r'(\w+)@(\w+)', r'\2/\1', 'a@b') # 替换时引用组,重排顺序
re.search(r'(?:ab)+c', 'ababc') # 只分组不记录,编号更干净分组写法对照
| 写法 | 是否记录内容 | 典型用途 |
|---|---|---|
| 普通圆括号 | 记录,占用编号 | 提取字段、替换引用 |
| 问号冒号开头的括号 | 不记录,不占编号 | 仅用于施加量词或限制分支 |
| 命名分组 | 记录,可用名字读取 | 字段多、可读性要求高的模式 |
| 断言括号 | 不记录,零宽 | 上下文条件判断 |
区分「组未参与匹配」与「组匹配到空串」是处理可选结构的关键。前者在很多语言里返回空值,后者返回空字符串,替换与判空逻辑必须分别处理。
分组编号按左括号出现顺序分配,嵌套时外层先编号。模式改动时插入一个新括号会把后续编号整体后移,替换逻辑随之失效,所以嵌套较深时建议改用命名分组。