为什么我不能匹配使用/(子模式)可能出现0或1次的子字符串?/

时间:2011-03-03 11:43:14

标签: regex perl

原始字符串是这样的:

checksession ok:6178 avg:479 avgnet:480 MaxTime:18081 fail1:19

最后一部分“ fail1:19 ”可能会出现0或1次。我尝试将“ fail1:”之后的数字与19匹配,使用此符号:

($reg_suc, $reg_fail) = ($1, $2) if $line =~ /^checksession\s+ok:(\d+).*(fail1:(\d+))?/;

它不起作用。即使“ fail1:19 ”确实存在,$ 2变量也是空的。如果我删除“?”,只有存在“ fail1:19 ”部分才能匹配。 $ 2变量将是“ fail1:19 ”。但如果“ fail1:19 ”部分不存在,则$ 1和$ 2都不匹配。这是不正确的。

如何重写此模式以正确捕获2号码?这意味着当存在“ fail1:19 ”部分时,将记录两个数字,当它不退出时,只有“ ok:”之后的数字将是记录。

4 个答案:

答案 0 :(得分:6)

首先,fail字段中的数字将以$3结尾,因为这些变量是根据左括号填充的。其次,正如codaddict所示,RE中的.*构造是饥饿的,所以它甚至会吃fail...部分。第三,你可以避免使用这样的编号变量:

my $line = "checksession ok:6178 avg:479 avgnet:480 MaxTime:18081 fail1:19";
if(my ($reg_suc, $reg_fail, $addend)
    = $line =~ /^checksession\s+ok:(\d+).*?(fail1:(\d+))?$/
) {
    warn "$reg_suc\n$reg_fail\n$addend\n";
}

答案 1 :(得分:2)

试试正则表达式:

^checksession\s+ok:(\d+).*?(fail1:(\d+))?$

Ideone Link

所做的更改:

    已经制作了中间的
  • .* 非贪婪和
  • $(结束锚)已被添加。

由于上述更改.*?将尝试尽可能少地使用,并且结束锚点强制正则表达式匹配,直到字符串结束,匹配fail1:number if

答案 2 :(得分:1)

我认为这是分裂实际上比正则表达式更强大的少数情况之一:

$bar[0]="checksession ok:6178 avg:479 avgnet:480 MaxTime:18081 fail1:19";
$bar[1]="checksession ok:6178 avg:479 avgnet:480 MaxTime:18081";
for $line (@bar){
    (@fields) = split/ /,$line;
    $reg_suc = $fields[1];
    $reg_fail = $fields[5];
    print "$reg_suc $reg_fail\n";
}

答案 3 :(得分:1)

我尽量避免使用非贪婪的修饰符。它经常咬回来。感谢建议分裂,但我会更进一步:

my %rec = split /\s+|:/, ( $line =~ /^checksession (.*)/ )[0];
print "$rec{ok} $rec{fail1}\n";