学习前提

理解字符类、量词与贪婪匹配;会读取exec返回值。

本课完成后你能做什么

从结构化文本提取字段,区分捕获与仅分组。

先理解机制

(a|b)把分支限定在组内。^cat|dog$表示以cat开头或以dog结尾,并不等价于^(?:cat|dog)$。先处理分支作用域,再检查锚点。

普通括号建立编号捕获;(?:...)只组织结构;(?<name>...)创建命名捕获。命名字段能减少插入新括号后编号变化导致的维护问题。

匹配成功不等于字段已完成语义验证。下例版本号允许无符号整数但不允许多位前导零;提取后的数字仍需按项目上限检查,避免超出安全整数范围。

可运行示例

const version = /^v(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)$/;
const match = version.exec("v12.3");
console.log(JSON.stringify(match ? [match.groups.major, match.groups.minor] : null));
console.log(version.test("v01.3"));
console.log(/^(?:cat|dog)$/.test("catfish"));
console.log(/^(?<word>[a-z]+)-\k<word>$/.test("go-go"));

推演与验证

命名捕获取得字符串12和3;v01.3与catfish被拒绝。命名反向引用要求第二段重复第一段,所以go-go通过。

常见错误与边界

不要直接访问失败匹配的groups;exec失败返回null。反向引用用于重复文本,不等于复制子模式再次匹配任意文本。

动手练习

增加patch字段,使v12.3.0通过,v12.3失败。

参考解法与理由

在末尾锚点前加入\.(?<patch>0|[1-9]\d*)。三个命名字段都保留字符串类型;转换数字前另做范围验证。

进一步阅读