如何在正则表达式中使用非捕获组,即(?:),它们有什么好处?
当前回答
在复杂的正则表达式中,可能会出现这样的情况:您希望使用大量的组,其中一些组用于重复匹配,另一些组用于提供反向引用。默认情况下,匹配每个组的文本将加载到backreference数组中。如果我们有很多组,并且只需要能够从backreference数组中引用其中的一些组,我们可以重写此默认行为,告诉正则表达式某些组只用于重复处理,不需要捕获并存储在backreference阵列中。
其他回答
我想我会给你答案。在未检查匹配是否成功的情况下,不要使用捕获变量。
除非匹配成功,否则捕获变量$1等无效,并且它们也不会被清除。
#!/usr/bin/perl
use warnings;
use strict;
$_ = "bronto saurus burger";
if (/(?:bronto)? saurus (steak|burger)/)
{
print "Fred wants a $1";
}
else
{
print "Fred dont wants a $1 $2";
}
在上面的示例中,为了避免在$1中捕获bronto,使用了(?:)。
如果模式匹配,则$1被捕获为下一个分组模式。
因此,输出如下:
Fred wants a burger
如果不希望保存匹配项,则此选项很有用。
历史动机:
非捕获组的存在可以用括号来解释。
考虑表达式(a|b)c和a|bc,由于串联优先于|,这些表达式分别表示两种不同的语言({ac,bc}和{a,bc})。
然而,括号也用作匹配组(如其他答案所解释的…)。
当您想有括号但不想捕获子表达式时,可以使用NON-CAPTURING GROUPS。在示例中,(?:a|b)c
我不能评论最上面的答案来这样说:我想补充一个明确的观点,这只是在最上面的回答中暗示的:
非捕获组(?…)不会从原始完全匹配中删除任何字符,它只会对程序员进行可视化的正则表达式重组。
要访问正则表达式的特定部分而不定义外来字符,您将始终需要使用.group(<index>)
它使组不捕获,这意味着该组匹配的子字符串将不包含在捕获列表中。ruby中的一个示例说明了区别:
"abc".match(/(.)(.)./).captures #=> ["a","b"]
"abc".match(/(?:.)(.)./).captures #=> ["b"]
让我举个例子:
Regex代码:(?:animal)(?:=)(\w+)(,)\1\2
搜索字符串:
第1行-动物=猫、狗、猫、老虎、狗
第2行-动物=猫、猫、狗、狗、老虎
第3行-动物=狗、狗、猫、猫、老虎
(?:动物)-->未捕获组1
(?:=)-->未捕获组2
(\w+)-->捕获的组1
(,)-->捕获的组2
\1-->捕获组1的结果,即第1行是猫,第2行是猫、第3行是狗。
\2-->捕获组2的结果,即逗号(,)
因此,在这段代码中,通过给出“1”和“2”,我们在代码后面分别回忆或重复捕获的组1和组2的结果。
根据代码的顺序,(?:动物)应为第1组,(?=)应为2组,并继续。。
但通过给出?:我们使匹配组不被捕获(在匹配组中不计数,因此分组编号从第一个捕获的组开始,而不是未捕获的组),这样以后就不能在代码中调用匹配组(?:动物)结果的重复。
希望这能解释非捕获组的使用。
推荐文章
- 如何从JavaScript中使用正则表达式的字符串中剥离所有标点符号?
- 正则表达式中的单词边界是什么?
- 如何将一个标题转换为jQuery的URL段塞?
- Javascript和regex:分割字符串并保留分隔符
- (grep)正则表达式匹配非ascii字符?
- 如何在保持原始字符串的同时对字符串执行Perl替换?
- 创建正则表达式匹配数组
- *的区别是什么?和。*正则表达式?
- 如何将“camelCase”转换为“Camel Case”?
- 在Java中使用正则表达式提取值
- Java中的正则表达式命名组
- 使用正则表达式搜索和替换Visual Studio代码
- 使用split("|")按管道符号拆分Java字符串
- 替换字符串中第一次出现的模式
- “\d”在正则表达式中是数字吗?