如何在正则表达式中使用非捕获组,即(?:),它们有什么好处?


当前回答

您可以使用捕获组来组织和分析表达式。非捕获组具有第一个好处,但没有第二个好处的开销。例如,您仍然可以说非捕获组是可选的。

假设你想匹配数字文本,但有些数字可以写成1、2、3、4,。。。如果要捕获数字部分,而不是(可选)后缀,则可以使用非捕获组。

([0-9]+)(?:st|nd|rd|th)?

这将匹配形式1、2、3…或形式1、第2、第3…的数字,。。。但它将只捕获数字部分。

其他回答

您可以使用捕获组来组织和分析表达式。非捕获组具有第一个好处,但没有第二个好处的开销。例如,您仍然可以说非捕获组是可选的。

假设你想匹配数字文本,但有些数字可以写成1、2、3、4,。。。如果要捕获数字部分,而不是(可选)后缀,则可以使用非捕获组。

([0-9]+)(?:st|nd|rd|th)?

这将匹配形式1、2、3…或形式1、第2、第3…的数字,。。。但它将只捕获数字部分。

捕获的组可以稍后在正则表达式中使用以匹配,也可以在正则表达式的替换部分中使用它们。创建一个非捕获组只会使该组免于出于以下原因之一而被使用。

如果你试图捕捉很多不同的东西,而有些群体你不想捕捉,那么非捕捉群体是很好的。

这就是它们存在的原因。当你学习团体时,学习原子团体,他们做了很多!也有环视组,但它们有点复杂,而且使用得不多。

稍后在正则表达式中使用的示例(backreference):

<([A-Z][A-Z0-9]*)\b[^>]*>.*</\1> [查找xml标记(不支持ns)]

([A-Z][A-Z0-9]*)是一个捕获组(在本例中是标记名)

稍后在正则表达式中是\ 1,这意味着它将仅与第一组([A-Z][A-Z0-9]*)中的相同文本匹配(在本例中,它与结束标记匹配)。

tl;dr非捕获组,顾名思义,是正则表达式中不希望包含在匹配中的部分,以及?:是一种将组定义为非捕获的方法。

假设你有一个电子邮件地址example@example.com.以下正则表达式将创建两个组,id部分和@example.com部分。(\p{Alpha}*[a-z])(@example.com)。为了简单起见,我们提取了包括@字符在内的整个域名。

现在让我们假设,您只需要地址的id部分。您要做的是获取匹配结果的第一个组,在正则表达式中用()包围,这样做的方法是使用非捕获组语法,即?:。因此,正则表达式(\p{Alpha}*[a-z])(?:@example.com)将只返回电子邮件的id部分。

让我举一个地理坐标的例子,下面是两组

Latitude,Longitude

([+-]?\d+(?:\.\d+)?),([+-]?\d+(?:\.\d+)?)

让我们拿一个([+-]?\d+(?:\.\d+)?)

坐标可以是58这样的整数,也可以是58.666因此,可选的(.666)第二部分(\.\d+)?被提及。

(...)? - for optional

但这是加括号的,这将是另一组匹配。我们不需要两场比赛,一场58分,另一场666分,我们需要一个纬度作为比赛。这里是非捕获组(?:)

与非捕获组[+-]?\d+(?:\.\d+)?,58.666和58都是单场比赛

我想我会给你答案。在未检查匹配是否成功的情况下,不要使用捕获变量。

除非匹配成功,否则捕获变量$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

如果不希望保存匹配项,则此选项很有用。