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

Day*_*Day 6 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);
}
Run Code Online (Sandbox Code Playgroud)

furtherProcessing如果有匹配,我希望被调用,任何捕获的组作为参数传递.当$regexp包含没有捕获组时问题就出现了,因为那样我想要furtherProcessing在没有参数的情况下调用,而不是使用1上面发生的值.我不能(1)像这样特殊情况进行测试

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

因为在这种情况下

$input = 'a value:1';
$regexp = qr/value:(\S+)/;
Run Code Online (Sandbox Code Playgroud)

有一个捕获的值,@captures看起来与$regexp匹配但没有捕获组时得到的相同.

有办法做我想要的吗?

cjm*_*cjm 8

您可以使用$#+以查找上次成功匹配中有多少组.如果那是0,那么你就没有任何团体(1).(是的,(1)如果没有任何组,它将永远存在,如perlop中所述.)

所以,这将做你想要的:

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

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

  • @ysth,我认为`$#+`本身就足够混淆了.:-) (2认同)