我们可以使用捕获组 (...) 的内容,不仅在结果或替换字符串中,而且在模式本身中。
按数字进行反向引用:\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!"
评论
<code>标签,对于多行代码,请用<pre>标签包裹,对于超过 10 行的代码,请使用沙盒(plnkr,jsbin,codepen…)