2010-10-21 52 views
10

如果我運行

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

我得到空字符串。 但是

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

輸出「2010」。爲什麼?

+0

有什麼奇怪的是'/ \ s([0-4] *)/'不具有相同的快捷行爲。它沒有說「我在空間的末尾匹配了零長度的字符串,在這裏你去。」 – Axeman 2010-10-21 14:12:55

+0

@Axeman,那是因爲'*'是貪婪的。數字在那裏,所以它抓住了他們。如果您與「2010年度」匹配,則「$ 1」將是第一個空格後面的零長度字符串。 – cjm 2010-10-21 16:08:36

回答

19

在第一個窗體的字符串「Year 2010」的開始處您會得到一個空匹配,因爲*會立即匹配0個數字。 +表單必須等到至少有一個數字在匹配之前。大概如果你可以通過全部第一種形式的比賽,你最終會發現2010 ...但可能只有在'e'之前發現另一個空比賽之後,然後在'a'之前,等等。

+0

太好了,謝謝! – alexanderkuk 2010-10-21 09:26:36

+0

Kleene星形生成的超集也包含空字符串,所以是的,它會匹配Y,e,a,r,whitespace之前的空字符串,然後它會找到2010。 – 2010-10-21 09:37:44

5

第一個匹配開始處的零長度字符串(在Y之前)並返回它。第二個搜索一個或多個數字並等待,直至找到2010

6

第一個正則表達式成功匹配字符串開頭的零個數字,這會導致捕獲空字符串。

第二個正則表達式匹配失敗在字符串的開頭,但是當它達到2010

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 
---------------------------------------------------------------------- 
1

星形符號試圖基本上匹配給定的0或多個符號(理論上,集合{X,Y} *由空字符串和所有可能的由x和y組成的有限序列),因此,它將在字符串的開始處精確匹配零個字符(空字符串),在第一個字符之後零個字符,在第二個字符之後零個字符等。然後最終它會找到2並匹配整個2010年。

加號符號與給定集合中的一個或多個字符匹配({x,y} +由x和y組成的所有可能的有限序列,沒有空字符串,而不是{x,y} *)。所以第一個符合的匹配字符是2,然後檢查下一個0,然後是1,然後是0,然後句子結束,因此找到的組看起來像'2010'。

這是正式表達式的標準行爲,在正式語言理論中定義。我強烈建議學習正則表達式有點理論,它不能傷害,但可以幫助:)

0

爲了使您的第一個RE匹配,使用錨「$」:

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

我們在學習Perl中將此作爲一個技巧性問題。可以匹配零個字符的任何正則表達式匹配零個字符。

Perl正則表達式引擎匹配最左邊的最長匹配,最左邊的部分最先匹配。不過,並非所有的正則表達式引擎都可以這樣工作。如果你想要所有的技術細節,請閱讀掌握正則表達式,它解釋了正則表達式引擎如何工作並找到匹配。

相關問題