JavaScript 正则表达式中的捕获组详解

JavaScript 正则表达式中的捕获组详解

【免费下载链接】ko.javascript.info 모던 JavaScript 튜토리얼(The Modern JavaScript Tutorial in Korean ) 【免费下载链接】ko.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ko/ko.javascript.info

正则表达式是 JavaScript 中处理字符串的强大工具,而捕获组(capturing groups)则是正则表达式中一个非常重要的概念。本文将深入讲解捕获组的各种用法和特性。

什么是捕获组

捕获组是通过在正则表达式中使用圆括号 () 来定义的。它有两个主要作用:

  1. 将匹配结果中的特定部分作为独立项提取出来
  2. 使量词作用于整个组而不仅是前一个字符

基本示例

// 不使用捕获组
console.log('goooo'.match(/go+/)); // 匹配 "goooo"

// 使用捕获组
console.log('gogogo'.match(/(go)+/)); // 匹配 "gogogo"

捕获组在匹配结果中的表现

当使用 str.match(regexp) 方法(不带 g 标志)时,返回的数组会包含完整的匹配和各个捕获组的内容:

let str = '<h1>Hello</h1>';
let result = str.match(/<(.*?)>/);

console.log(result[0]); // "<h1>" - 完整匹配
console.log(result[1]); // "h1" - 第一个捕获组

嵌套捕获组

当捕获组嵌套时,编号是从左到右按开括号的顺序分配的:

let str = '<span class="my">';
let regexp = /<(([a-z]+)\s*([^>]*))>/;
let result = str.match(regexp);

// result[0]: "<span class="my">" (完整匹配)
// result[1]: "span class="my" (外层捕获组)
// result[2]: "span" (标签名)
// result[3]: "class="my"" (属性)

可选捕获组

即使捕获组是可选的(使用了 ? 量词),在结果数组中仍然会保留位置,值为 undefined

let match = 'a'.match(/a(z)?(c)?/);
console.log(match[1]); // undefined
console.log(match[2]); // undefined

使用 matchAll 获取所有匹配的捕获组

当需要获取所有匹配项及其捕获组时,可以使用 matchAll 方法:

let str = '<h1> <h2>';
let results = str.matchAll(/<(.*?)>/g);

for (let result of results) {
  console.log(result[0]); // 完整匹配
  console.log(result[1]); // 捕获组内容
}

matchAll 返回一个可迭代对象,而不是数组,这样可以优化性能。

命名捕获组

为了更清晰地引用捕获组,可以使用命名捕获组:

let dateRegexp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let str = "2023-05-15";
let result = str.match(dateRegexp);

console.log(result.groups.year);  // "2023"
console.log(result.groups.month); // "05"
console.log(result.groups.day);   // "15"

在替换中使用捕获组

在字符串替换时,可以引用捕获组:

// 使用编号引用
let str1 = "John Smith";
console.log(str1.replace(/(\w+) (\w+)/, '$2, $1')); // "Smith, John"

// 使用命名引用
let dateStr = "2023-05-15";
console.log(dateStr.replace(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/, '$<day>/$<month>/$<year>')); // "15/05/2023"

非捕获组

如果只需要分组但不需捕获内容,可以使用非捕获组 (?:...)

let str = "Gogogo John!";
let result = str.match(/(?:go)+ (\w+)/);

console.log(result[0]); // "Gogogo John"
console.log(result[1]); // "John"
console.log(result.length); // 2 (没有额外的捕获组)

实际应用示例

域名匹配

let regexp = /([\w-]+\.)+\w+/g;
console.log("site.com my.site.com".match(regexp)); // ["site.com", "my.site.com"]

邮箱验证

let emailRegexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g;
console.log("test@example.com user.name@sub.domain.com".match(emailRegexp));

总结

  1. 捕获组使用圆括号 () 定义,可以提取匹配的子字符串
  2. 捕获组按从左到右的顺序编号,从 1 开始
  3. 可以使用命名捕获组 (?<name>...) 提高可读性
  4. matchAll 方法可以获取所有匹配及其捕获组
  5. 在替换字符串中可以使用 $n$<name> 引用捕获组
  6. 非捕获组 (?:...) 用于只分组不捕获的场景

掌握捕获组的使用可以大大增强正则表达式的功能,使字符串处理更加灵活高效。

【免费下载链接】ko.javascript.info 모던 JavaScript 튜토리얼(The Modern JavaScript Tutorial in Korean ) 【免费下载链接】ko.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ko/ko.javascript.info

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值