按名字取分组结果
匹配成功之后,用分组名而不是序号去取值:名字在模式与代码里成对出现,插入新分组不会让取值代码整体错位,长模式里也不用回去数括号。代价是不同语言取名字的 API 与「组没参与匹配」时的返回值都不一样,写跨语言代码时要单独确认。
基本信息
| 取值时机 | 必须在匹配成功之后,对未匹配或 None 的结果取组会报错 |
|---|---|
| 未参与分组 | Python 为 None,JS 为 undefined,Java 为 null,PHP 为空字符串 |
| 命名前提 | 模式里必须用命名语法声明分组,序号组无法按名字取 |
| 整体匹配 | 组 0 是整段匹配,命名组从 1 开始另行编号 |
典型使用场景
- 日志解析:从一行日志里按字段名取出时间、IP、状态码,代码不依赖括号顺序
- URL 与路径拆分:把协议、主机、路径、查询串分别命名,后续按字段拼装或校验
- 多分支模式取值:不同分支用同一个名字,代码侧取值逻辑只写一份
- 模式演进:新增或调整分组顺序后,取值代码不受影响,降低回归风险
- 团队协作:模式由运维维护、取值由应用消费,命名比序号更容易沟通
各语言取值写法
各语言取值写法
m = re.search(pat, s); m.group('host') # Python:按名字取,组未参与返回 None
m.groupdict() # Python:一次拿到全部命名组
const g = s.match(pat).groups.host; # JS:groups 属性,组未参与为 undefined
preg_match($pat, $s, $m); $m['host']; # PHP:命名键与序号键同时存在
m.group("host") # Java:未参与的组返回 null,记得判空
// Ruby: md[:host]、md.named_captures # Ruby 用符号取值各语言取值对照
| 语言 | 按名字取值 | 未参与时 |
|---|---|---|
| Python | m.group('name') 或 m.groupdict() | None |
| JavaScript | m.groups.name | undefined |
| PHP | $m['name'] | 空字符串 |
| Java | m.group("name") | null |
| Go | 索引 = re.SubexpIndex("name") 后取切片 | 空切片 |
Go 的 regexp 没有按名字直接取值的接口,需要先用 SubexpIndex 把组名换成序号再取 FindStringSubmatch 的对应元素;这一步常被漏掉,导致取值代码写得很绕。
分支交替时容易出现同名分组:JS 与 Python 对重复组名的接受程度不同,Python re 禁止两个同名组,跨引擎复用模式前先确认目标引擎允许的组名规则。