为什么“2010年”=〜/([0-4] *)/会导致$ 1中的空字符串?

时间:2010-10-21 09:19:34

标签: regex perl

如果我跑

"Year 2010" =~ /([0-4]*)/;
print $1;

我得到空字符串。 但

"Year 2010" =~ /([0-4]+)/;
print $1;

输出“2010”。为什么呢?

7 个答案:

答案 0 :(得分:19)

您在第一个表单的字符串“Year 2010”的开头获得一个空匹配,因为*将立即匹配0位数。 +表单必须等到至少有一个数字才能匹配。

大概如果你可以通过所有第一个表格的匹配,你最终会找到2010 ...但可能只是在它找到'e'之前的另一个空匹配之后, 'a'等。

答案 1 :(得分:6)

第一个正则表达式在字符串开头成功匹配零位数,从而捕获空字符串。

第二个正则表达式在字符串的开头不匹配,但在到达2010时确实匹配。

答案 2 :(得分:5)

第一个匹配开头的零长度字符串(在Y之前)并返回它。第二个搜索一个或多个数字并等待它找到2010

答案 3 :(得分:5)

您也可以使用YAPE::Regex::Explain来解释正则表达式,例如

use YAPE::Regex::Explain;

print YAPE::Regex::Explain->new('([0-4]*)')->explain();
print YAPE::Regex::Explain->new('([0-4]+)')->explain();

输出:

The regular expression:
(?-imsx:([0-4]*))
matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    [0-4]*                   any character of: '0' to '4' (0 or more
                             times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

The regular expression:
(?-imsx:([0-4]+))
matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    [0-4]+                   any character of: '0' to '4' (1 or more
                             times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

答案 4 :(得分:1)

星形符号试图在给定集合中基本匹配0个或多个符号(理论上,集合{x,y} *由空字符串和由x和y组成的所有可能的有限序列组成),因此,它将在字符串的开头匹配零个字符(空字符串),第一个字符后面的零个字符,第二个字符后面的零个字符,等等。最后它将找到2并匹配整个2010。

加号符号与给定集合中的一个或多个字符匹配({x,y} +由x和y组成的所有可能的有限序列组成,没有空字符串,而不是{x,y} *)。所以第一个匹配的匹配字符是2,然后是next - 0被检查,然后是1,然后是另一个0,然后句子结束,所以找到的组看起来像'2010'。

它是正则语言理论中定义的正则表达式的标准行为。我强烈建议学习一些关于正则表达式的理论,它不会伤害,但可以帮助:)

答案 5 :(得分:1)

我们在 Learning Perl 中将此作为一个技巧问题。任何可以匹配在字符串开头不匹配的零字符的正则表达式都将匹配零个字符。

Perl正则表达式引擎匹配最左边的最长匹配,最左边的部分首先匹配。但并非所有的正则表达式引擎都能像这样工作。如果您需要所有技术细节,请阅读掌握正则表达式,它解释了正则表达式引擎如何工作并找到匹配项。

答案 6 :(得分:0)

要进行首次RE匹配,请使用锚点“ $ ”:

"Year 2010" =~ /([0-4]*)$/;
 print $1;