">"> ">
2020 年 5 月 19 日

模式中的反向引用:\N 和 \k<name>

我们可以使用捕获组 (...) 的内容,不仅在结果或替换字符串中,而且在模式本身中。

按数字进行反向引用:\N

可以使用 \N 在模式中引用组,其中 N 是组号。

为了说明为什么这很有用,让我们考虑一个任务。

我们需要找到带引号的字符串:单引号 '...' 或双引号 "..." – 两种变体都应该匹配。

如何找到它们?

我们可以将两种引号都放在方括号中:['"](.*?)['"],但这会找到带有混合引号的字符串,例如 "...''..."。当一个引号出现在另一个引号内部时,例如在字符串 "She's the one!" 中,这会导致不正确的匹配。

let str = `He said: "She's the one!".`;

let regexp = /['"](.*?)['"]/g;

// The result is not what we'd like to have
alert( str.match(regexp) ); // "She'

正如我们所见,该模式找到了一个开头的引号 ",然后文本被消耗到另一个引号 ',它关闭了匹配。

为了确保模式寻找的结束引号与开头引号完全相同,我们可以将其包装在一个捕获组中并进行反向引用:(['"])(.*?)\1

以下是正确的代码

let str = `He said: "She's the one!".`;

let regexp = /(['"])(.*?)\1/g;

alert( str.match(regexp) ); // "She's the one!"

现在它可以工作了!正则表达式引擎找到第一个引号 (['"]) 并记住其内容。这是第一个捕获组。

在模式中,\1 表示“找到与第一个组中相同的文本”,在本例中是完全相同的引号。

类似地,\2 将表示第二个组的内容,\3 表示第三个组的内容,依此类推。

请注意

如果我们在组中使用 ?:,那么我们就无法引用它。从捕获中排除的组 (?:...) 不会被引擎记住。

不要搞混:在模式 \1 中,在替换中:$1

在替换字符串中,我们使用美元符号:$1,而在模式中使用反斜杠 \1

按名称反向引用:\k<name>

如果一个正则表达式有许多括号,给它们命名会很方便。

要引用一个命名组,我们可以使用 \k<name>

在下面的示例中,带有引号的组名为 ?<quote>,因此反向引用为 \k<quote>

let str = `He said: "She's the one!".`;

let regexp = /(?<quote>['"])(.*?)\k<quote>/g;

alert( str.match(regexp) ); // "She's the one!"
教程地图

评论

在评论之前请阅读…
  • 如果您有改进建议,请提交 GitHub 问题或拉取请求,而不是评论。
  • 如果您不理解文章中的某些内容,请详细说明。
  • 要插入少量代码,请使用<code>标签,对于多行代码,请用<pre>标签包裹,对于超过 10 行的代码,请使用沙盒(plnkrjsbincodepen…)