我们可以使用捕获组 (...)
的内容,不仅在结果或替换字符串中,而且在模式本身中。
按数字进行反向引用:\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…)