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

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

ru.javascript.info Современный учебник JavaScript ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

正则表达式是 JavaScript 中处理字符串的强大工具,而分组捕获则是正则表达式中一个极其重要的功能。本文将深入讲解 JavaScript 正则表达式中的分组技术,帮助开发者更好地掌握这一功能。

什么是分组捕获

在正则表达式中,使用圆括号 () 可以将部分模式组合在一起,形成一个分组。这种分组有两个主要作用:

  1. 将匹配到的内容单独提取出来,便于后续处理
  2. 对分组内的整个内容应用量词(如 +, *, ? 等)

基础分组示例

简单重复匹配

考虑一个简单的例子,我们想匹配连续的 "go" 字符串:

console.log('Gogogo now!'.match(/(go)+/ig)); // 输出 ["Gogogo"]

这里 (go)+ 表示匹配一个或多个连续的 "go" 字符串,而不只是匹配 "g" 后面跟着多个 "o"。

域名匹配

更实用的例子是匹配网站域名:

const domainRegex = /(\w+\.)+\w+/g;
console.log("site.com my.site.com".match(domainRegex)); 
// 输出 ["site.com", "my.site.com"]

这个正则表达式可以匹配多级域名,但需要注意它无法匹配包含连字符的域名(如 "my-site.com"),因为 \w 不包含连字符。

分组内容的获取

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

const str = '<h1>Hello, world!</h1>';
const tag = str.match(/<(.*?)>/);

console.log(tag[0]); // 输出 "<h1>" (完整匹配)
console.log(tag[1]); // 输出 "h1" (第一个分组内容)

嵌套分组处理

分组可以嵌套使用,每个分组按左括号出现的顺序编号:

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

console.log(result[0]); // 完整匹配: <span class="my">
console.log(result[1]); // 第一分组: span class="my"
console.log(result[2]); // 第二分组: span
console.log(result[3]); // 第三分组: class="my"

可选分组处理

即使分组是可选的(使用 ? 量词),结果数组中对应的位置仍然存在,值为 undefined

const match = 'a'.match(/a(z)?(c)?/);
console.log(match.length);  // 3
console.log(match[0]);      // "a"
console.log(match[1]);      // undefined
console.log(match[2]);      // undefined

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

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

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

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

matchAll() 返回一个可迭代对象,每个匹配项都是一个包含完整匹配和分组内容的数组。

命名分组

为了提高代码可读性,ES2018 引入了命名分组:

const dateRegexp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const str = "2019-04-30";
const groups = str.match(dateRegexp).groups;

console.log(groups.year);  // "2019"
console.log(groups.month); // "04"
console.log(groups.day);   // "30"

分组在替换中的应用

分组内容可以在替换字符串中引用:

let str = "John Bull";
console.log(str.replace(/(\w+) (\w+)/, '$2, $1')); // "Bull, John"

// 使用命名分组
const dateStr = "2019-10-30";
console.log(dateStr.replace(
  /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
  '$<day>.$<month>.$<year>'
)); // "30.10.2019"

非捕获分组

如果只需要分组但不需捕获内容,可以使用 ?: 前缀:

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

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

总结

正则表达式的分组功能非常强大,主要特点包括:

  1. 使用 () 创建分组,可以嵌套使用
  2. 分组内容可以通过 match()matchAll() 获取
  3. ES2018 引入命名分组,提高代码可读性
  4. 分组内容可用于替换操作
  5. 使用 ?: 创建非捕获分组,不保留匹配内容

掌握这些分组技术将大大提升你处理复杂字符串模式的能力,使正则表达式更加灵活和强大。

ru.javascript.info Современный учебник JavaScript ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董向越

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

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

抵扣说明:

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

余额充值