正则表达式捕获组详解:从入门到掌握
1. 什么是捕获组(Capture Group)?
捕获组是正则表达式中用于==捕获子匹配内容==的语法,通过 ()
包裹的部分会被单独记录。它是处理复杂文本匹配时最常用的功能之一。
关键特性
- 提取子内容:从完整匹配中分离出特定部分
- 索引编号:从左到右按
(
出现的顺序分配编号(从1开始) - 复用匹配:可在同个正则表达式中反向引用
2. 基础语法与示例
2.1 简单捕获组
const text = "2023-10-01";
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const match = text.match(regex);
console.log(match);
// 输出: [
// "2023-10-01", // 完整匹配
// "2023", // 第1捕获组(年)
// "10", // 第2捕获组(月)
// "01" // 第3捕获组(日)
// ]
2.2 为什么会出现多个结果?
match()
返回数组的结构:
[
0: "完整匹配内容",
1: "第1个捕获组内容",
2: "第2个捕获组内容",
...
groups: undefined, // 命名捕获组时使用
index: 匹配起始位置,
input: 原始字符串
]
3. 关联核心概念
3.1 非捕获组 (Non-Capturing Group)
使用(?:...)
语法声明不捕获内容的分组,节省内存且提升性能。
const regex = /(?:\d{4})-(?:\d{2})/;
"2023-10".match(regex);
// 输出: ["2023-10"] (没有捕获组内容)
3.2 命名捕获组 (Named Capture Group)
ES6+
支持通过?<name>
语法给捕获组命名,提升可读性。
const regex = /(?<year>\d{4})-(?<month>\d{2})/;
const { groups } = "2023-10".match(regex);
console.log(groups.year); // "2023"
console.log(groups.month); // "10"
3.3 反向引用 (Backreference)
在正则表达式中使用 \n
引用已捕获的内容:
// 匹配重复的单词
const regex = /(\b\w+\b)\s+\1/;
"hello hello world".match(regex);
// 匹配到 "hello hello",\1 引用了第1个捕获组的 "hello"
3.4 零宽断言 (Lookaround Assertions)
类型 | 语法 | 作用 |
---|---|---|
正向先行断言 | (?=...) |
匹配后面是…的位置 |
负向先行断言 | (?!...) |
匹配后面不是…的位置 |
正向后行断言 | (?<=...) |
匹配前面是…的位置 |
负向后行断言 | (?<!...) |
匹配前面不是…的位置 |
4. 常见问题解答
4.1 为什么 match() 返回多个结果?
- 索引
0
始终是完整匹配内容 - 后续索引对应捕获组顺序
- 使用
match
获取第一个捕获组内容
4.2 如何处理多个捕获组?
// 提取电话号码的区号和后缀
const regex = /$(\d{3})$[\s-]?(\d{4}-\d{4})/;
const [full, areaCode, number] = "(021)1234-5678".match(regex);
console.log(areaCode); // "021"
console.log(number); // "1234-5678"
4.3 为什么捕获组返回 undefined?
- 当捕获组没有匹配到内容时会返回
undefined
- 使用可选链操作避免报错:
match.groups?.name
5. 开发技巧
5.1 贪婪 vs 非贪婪模式
- 默认使用贪婪匹配(尽可能多匹配)
- 在量词后加
?
切换为非贪婪模式:
// 贪婪模式
"a<b>test</b>c".match(/<(.*)>/);
// 捕获组内容: "b>test</b"
// 非贪婪模式
"a<b>test</b>c".match(/<(.*?)>/);
// 捕获组内容: "b"
5.2 性能优化建议
- 避免过度使用捕获组
- 不需要捕获内容时使用非捕获组
(?:)
- 复杂正则表达式优先使用命名捕获组
6. 总结
功能 | 语法 | 典型应用场景 |
---|---|---|
普通捕获组 | (...) |
提取日期各部分 |
命名捕获组 | (?<name>...) |
提高复杂正则可读性 |
非捕获组 | (?:...) |
仅分组不提取内容 |
反向引用 | \1 |
匹配重复内容 |
掌握捕获组能显著提升正则表达式的实用性。