代码之家  ›  专栏  ›  技术社区  ›  Sundar R

为什么我的非贪婪PerlRegex不匹配?

  •  4
  • Sundar R  · 技术社区  · 17 年前

    我认为我在某种程度上理解了Perl Re,但这让我困惑:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my $test = "'some random string'";
    
    if($test =~ /\'?(.*?)\'?/) {
           print "Captured $1\n";
           print "Matched $&";
    }
    else {
           print "What?!!";
    }
    

    印刷品

    捕获
    匹配的

    它似乎与结局“独树一帜”,所以什么也没有捕捉到。
    我本以为它会匹配整个事物,或者如果它完全不贪婪,什么都没有(因为所有事物都有可选的匹配)。
    这中间的行为让我困惑,有人能解释发生了什么吗?

    5 回复  |  直到 14 年前
        1
  •  14
  •   Simon Nickerson    17 年前

    这个 \'? 在开始和结束时意味着 贪婪地匹配0或1撇号 . (正如另一张海报所指出的,要使它不贪婪,它必须 \'?? )

    这个 .*? 中间的意思是 不贪婪地匹配0个或多个字符 .

    Perl正则表达式引擎将查看字符串的第一部分。它将匹配开头,但却如此贪婪,因此它开始使用第一个撇号。然后它不贪婪地匹配(尽可能少地匹配),后面跟着一个可选的撇号。这与空字符串匹配。

        2
  •  3
  •   Tomalak    17 年前

    我想你的意思是:

    /'(.*?)'/      // matches everything in single quotes
    

    /'[^']*'/      // matches everything in single quotes, but faster
    

    阿法克,单引号不需要被转义。

        3
  •  2
  •   Chas. Owens    17 年前

    pattern? 贪婪,如果你想让它变得不贪婪,你必须说 pattern?? :

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my $test = "'some random string'";
    
    if($test =~ /\'?(.*?)\'?/) {
           print "Captured [$1]\n";
           print "Matched  [$&]\n";
    }
    if($test =~ /\'??(.*?)\'??/) {
           print "Captured [$1]\n";
           print "Matched  [$&]\n";
    }
    

    来自Perldoc Perlre:

    可识别以下标准量词:

    *      Match 0 or more times
    +      Match 1 or more times
    ?      Match 1 or 0 times
    {n}    Match exactly n times
    {n,}   Match at least n times
    {n,m}  Match at least n but not more than m times
    

    默认情况下,一个量化的子模式是“贪婪的”,也就是说,它将匹配 尽可能多次(给定特定的起始位置),同时 仍然允许模式的其余部分匹配。如果你想的话 匹配尽可能少的次数,跟随量词 A“?”注意,意思不会改变,只是“贪婪”而已:

    *?     Match 0 or more times
    +?     Match 1 or more times
    ??     Match 0 or 1 time
    {n}?   Match exactly n times
    {n,}?  Match at least n times
    {n,m}? Match at least n but not more than m times
    
        4
  •  1
  •   kixx    17 年前

    注意不要让regex的所有元素都是可选的(即用*或?对所有元素进行量化)。。这使得PerlRegex引擎可以随心所欲地匹配(甚至什么都不匹配),同时仍然考虑匹配是否成功。

    我怀疑你想要的是

    /'(.*?)'/
    
        5
  •  1
  •   Rini    17 年前

    我想说最接近你要找的答案是

    /'?([^']*)'?/
    

    因此,“如果有单引号就得到单引号”,“得到任何不是单引号的东西”,“如果有最后一个单引号就得到”。

    除非你想匹配“‘不要这样做’”—但是谁会在一个单引号中使用撇号(并且长时间地摆脱它)?:)