此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

View in English Always switch to English

组和反向引用

组将多个模式组合为一个整体,而在使用正则表达式模式与字符串进行匹配时,捕获组会提供额外的子匹配信息。反向引用是指同一正则表达式中先前捕获的组。

尝试一下

// 组
const imageDescription = "This image has a resolution of 1440×900 pixels.";
const regexpSize = /(\d+)×(\d+)/;
const match = imageDescription.match(regexpSize);
console.log(`Width: ${match[1]} / Height: ${match[2]}.`);
// 期望输出:"Width: 1440 / Height: 900."

// 反向引用
const findDuplicates = "foo foo bar";
const regex = /\b(\w+)\s+\1\b/g;
console.log(findDuplicates.match(regex));
// 期望输出:Array ["foo foo"]

类型

字符集 含义
x|y

匹配 "x" 或 "y" 任意一个字符。例如, /green|red/ 在 "green apple" 里匹配 "green",且在 "red apple" 里匹配 "red" 。

[xyz]
[a-c]

字符集。 匹配任何一个包含的字符。你可以使用连字符来指定字符范围,但如果连字符显示为方括号中的第一个或最后一个字符,则它将被视为作为普通字符包含在字符集中的文字连字符。也可以在字符集中包含字符类。

例如,[abcd] 是与[a-d].一样的,它们会 在"brisket" 中匹配 "b",在 "chop" 中匹配 "c" .

例如,[abcd-][-abcd] 将会在 "brisket" 匹配 "b" , 在 "chop" 匹配 "c" , 并且匹配 "non-profit" 中的 "-" (连字符)

例如,[\w-] 是字符集 \w 和 “-”(连字符)的并集,与这种写法一样: [A-Za-z0-9_-].。他们都会 在 "brisket"中匹配“b”, 在 "chop"中匹配“c”, 在 "non-profit" 中匹配 "n"。

[^xyz]
[^a-c]

一个否定的或被补充的字符集。也就是说,它匹配任何没有包含在括号中的字符。可以通过使用连字符来指定字符范围,但是如果连字符作为方括号中的第一个或最后一个字符出现,那么它将被视为作为普通字符包含在字符集中。例如,[^abc] 和 [^a-c] 一样。它们最初匹配“bacon”中的“o”和“chop”中的“h”。

备注: ^ 字符也可以表示 输入的起始

(x)

捕获组:匹配 x 并记住匹配项。例如,/(foo)/匹配并记住“foo bar”中的“foo”

正则表达式可以有多个捕获组。结果,匹配通常在数组中捕获的组,该数组的成员与捕获组中左括号的顺序相同。这通常只是捕获组本身的顺序。当捕获组被嵌套时,这一点非常重要。使用结果元素的索引 ([1], ..., [n]) 或从预定义的 RegExp 对象的属性 ($1, ..., $9).

捕获组会带来性能损失。如果不需要收回匹配的子字符串,请选择非捕获括号 (见下面)。

String.match() 不会返回组,如果设置了 /.../g 标志。但是,你仍然可以使用 String.matchAll() to get all matches.

match() 不会返回组,如果/…但是,你仍然可以使用 String.matchAll() 来获取所有匹配项。

\n

反向引用:其中“n”是一个正整数。匹配正则表达式中第 n 个捕获组(按左括号计数)所匹配的相同子字符串。例如,/apple(,)\sorange\1/ 匹配“apple, orange, cherry, peach”中的“apple, orange”。

(?<Name>x)

具名捕获组:匹配"x"并将其存储在返回的匹配项的 groups 属性中,该属性位于<Name>指定的名称下。尖括号 (<>) 用于组名。

例如,使用正则 /-(?<customName>\w)/ 匹配“web-doc” 中的“d”

'web-doc'.match(/-(?<customName>\w)/).groups //{customName: "d"}

(?:x) 非捕获组:匹配 “x”,但不记得匹配。不能从结果数组的元素中收回匹配的子字符串 ([1], ..., [n]) or from the predefined RegExp object's properties ($1, ..., $9).

示例

使用组

js
let personList = `First_Name: John, Last_Name: Doe
First_Name: Jane, Last_Name: Smith`;

let regexpNames = /First_Name: (\w+), Last_Name: (\w+)/gm;
let match = regexpNames.exec(personList);
do {
  console.log(`Hello ${match[1]} ${match[2]}`);
} while ((match = regexpNames.exec(personList)) !== null);

使用命名组

js
let users = `姓氏:李,名字:雷
姓氏:韩,名字:梅梅`;

let regexpNames = /姓氏:(?<first>.+),名字:(?<last>.+)/gm;
let match = regexpNames.exec(users);

do {
  console.log(`Hello ${match.groups.first} ${match.groups.last}`);
} while ((match = regexpNames.exec(users)) !== null);

// Hellow 李 雷
// Hellow 韩 梅梅

使用组和反向引用

在此示例中,我们首先使用 ['"] 匹配单引号或双引号字符,将其记在 \1 中;接着使用 .*? 匹配任意数量的字符(*? 是一个非贪婪量词),直到再次使用 \1 匹配到之前记下的引号字符。\1 是对第一个捕获组的反向引用,该捕获组匹配的是同类型的引号。因此,结果将是两个字符串:"'"'"'

js
const quote = `Single quote "'" and double quote '"'`;
const regexpQuotes = /(['"]).*?\1/g;
for (const match of quote.matchAll(regexpQuotes)) {
  console.log(match[0]);
}

更多示例请参见反向引用参考文档。

参见