检测列表上下文中的匹配与捕获与非捕获正则表达式的区别?

时间:2011-05-21 22:43:16

标签: regex perl

根据perlretut

  

...在标量上下文中,$time =~ /(\d\d):(\d\d):(\d\d)/返回true或false值。但是,在列表上下文中,它返回匹配值($1,$2,$3)的列表。

但是如果在regexp中没有捕获组时模式匹配,我找不到列表上下文中返回内容的解释。测试显示它是列表(1)(单个元素,整数1)。 (辅助问题 - 它总是这样,它定义在哪里?)

这使得我很难做到我想要的事情:

if (my @captures = ($input =~ $regexp)) {
    furtherProcessing(@captures);
}

如果匹配,我希望调用furtherProcessing,并将任何捕获的组作为参数传递。当$regexp不包含任何捕获组时问题就出现了,因为我希望furtherProcessing不需要参数调用,而不是使用上面发生的值1。我无法测试(1)作为特殊情况,例如

if (my @captures = ($input =~ $regexp)) {
    shift @captures if $captures[0] == 1;
    furtherProcessing(@captures);
}

因为在

的情况下
$input = 'a value:1';
$regexp = qr/value:(\S+)/;

@captures中的捕获值恰好与$regexp匹配但没有捕获组时的值相同。

有办法做我想做的事吗?

1 个答案:

答案 0 :(得分:8)

您可以使用$#+查找上次成功比赛中有多少组。如果那是0,则没有组,你有(1)。 (是的,如果没有组,它将始终为(1),如perlop中所述。)

所以,这会做你想要的:

if (my @captures = ($input =~ $regexp)) {
    @captures = () unless $#+; # Only want actual capture groups
    furtherProcessing(@captures);
}

请注意$#+计算所有组,无论它们是否匹配(只要整个RE匹配)。因此,"hello" =~ /hello( world)?/将返回1个组,即使该组不匹配(@captures中的值将为undef)。