正则表达式中的非捕获组是什么?

正则表达式中的非捕获组是什么?

技术背景

在正则表达式中,捕获组是用括号 () 括起来的部分,它会在匹配过程中保存匹配到的文本,方便后续引用。但有时,我们只需要对某些部分进行分组,用于限定匹配规则,而不需要保存匹配结果,这时就需要用到非捕获组。非捕获组使用 (?:) 语法,它能提高正则表达式的性能,减少内存开销,并且简化捕获组的编号。

实现步骤

定义非捕获组

使用 (?:) 来定义非捕获组。例如,(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)? 中,(?:https?|ftp) 就是一个非捕获组,用于匹配协议部分,但不会将其作为捕获组保存。

应用非捕获组

在正则表达式中,非捕获组可以用于多种场景,如匹配 URL、日期、数字等。以下是一些具体示例:

匹配 URL

1
2
3
4
5
6
7
const text = `http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex`;
const regex = /(?:https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
const matches = text.match(regex);
if (matches) {
console.log(matches);
}

上述代码中,非捕获组 (?:https?|ftp) 用于匹配协议部分,捕获组 ([^/\r\n]+) 用于匹配主机名,捕获组 (\/[^\r\n]*)? 用于匹配路径。

匹配数字和可选后缀

1
2
3
4
5
6
const text = '1st 2 3rd 4th';
const regex = /([0-9]+)(?:st|nd|rd|th)?/g;
let match;
while ((match = regex.exec(text))!== null) {
console.log(match[1]);
}

上述代码中,非捕获组 (?:st|nd|rd|th)? 用于匹配可选的后缀,但不会将其作为捕获组保存,只捕获数字部分。

匹配 IP 地址

1
2
3
4
5
6
const text = '192.168.1.1';
const regex = /(?:\d{1,3}\.){3}\d{1,3}/;
const matches = text.match(regex);
if (matches) {
console.log(matches[0]);
}

上述代码中,非捕获组 (?:\d{1,3}\.){3} 用于匹配前三个八位字节,但不会将其作为捕获组保存,只匹配整个 IP 地址。

核心代码

以下是一个完整的 JavaScript 示例,演示了非捕获组的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 匹配 URL
const urlText = `http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex`;
const urlRegex = /(?:https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/g;
let urlMatch;
while ((urlMatch = urlRegex.exec(urlText))!== null) {
console.log(`主机名: ${urlMatch[1]}`);
console.log(`路径: ${urlMatch[2]}`);
}

// 匹配数字和可选后缀
const numberText = '1st 2 3rd 4th';
const numberRegex = /([0-9]+)(?:st|nd|rd|th)?/g;
let numberMatch;
while ((numberMatch = numberRegex.exec(numberText))!== null) {
console.log(`数字: ${numberMatch[1]}`);
}

// 匹配 IP 地址
const ipText = '192.168.1.1';
const ipRegex = /(?:\d{1,3}\.){3}\d{1,3}/;
const ipMatches = ipText.match(ipRegex);
if (ipMatches) {
console.log(`IP 地址: ${ipMatches[0]}`);
}

最佳实践

  • 减少不必要的捕获:当只需要对部分内容进行分组,而不需要保存匹配结果时,使用非捕获组可以减少捕获组的数量,提高性能。
  • 简化正则表达式:非捕获组可以使正则表达式更加简洁,易于理解和维护。
  • 注意嵌套情况:非捕获组可以嵌套在捕获组中,也可以包含捕获组。在嵌套时,要注意捕获组的编号和引用。

常见问题

非捕获组是否会影响整个匹配结果?

非捕获组不会影响整个匹配结果,它只是不保存匹配的文本。整个正则表达式的匹配仍然按照规则进行。

如何引用非捕获组中的内容?

非捕获组不会保存匹配的文本,因此无法直接引用。如果需要引用某个部分,应该使用捕获组。

非捕获组和捕获组的性能差异大吗?

在大多数情况下,非捕获组的性能略高于捕获组,因为它不需要保存匹配的文本。但在简单的正则表达式中,这种差异可能不明显。


正则表达式中的非捕获组是什么?
https://119291.xyz/posts/2025-05-14.what-is-a-non-capturing-group-in-regular-expressions/
作者
ww
发布于
2025年5月14日
许可协议