2016-08-30 73 views
1

我得到了以下情況:非貪婪通配符「忽略」

...  
preg_match('/#(.+?):(.+?)#/im','partA#partB#partC:partD#partE#partF',$matches); 
... 

執行$比賽後成爲

Array 
    (
     [0] => #partB#partC:partD# 
     [1] => partB#partC 
     [2] => partD 
    ) 

豈不是正常的$matches[1]成爲partC如果我使用非貪婪通配符??我錯過了什麼嗎?

我設法通過使用'/#([^#]+?):([^#]+?)#/im'作爲模式來解決這個問題,但一個相關的解釋對於清除雲是很好的。

感謝。

+1

實際上,你可以使用''/#([^#:] +)([^#] +)#/「'。重點是* lazy *量詞不保證最短匹配,並且正則表達式引擎(默認)從左到右處理字符串。一旦找到有效的符號,就會從最左邊的位置到右邊嘗試其餘的模式。所以,'partB#partC'對'。+?'可以。 –

+1

要理解,正則表達式引擎從左到右搜索字符串,並嘗試在字符串中的每個位置成功。 –

+1

我在你的正則表達式'#'中看到':'到'#'。與'abc'匹配############################################# ################################:#'def'。你看到的是'#:#'。原因在於你想看到的是人性。 – sln

回答

1

當您考慮正則表達式背後的基礎理論時,這是有道理的。

正則表達式就是所謂的finite state automaton (FSA)。這意味着它本質上會一次處理一個字符,從左到右,偶爾會通過「放棄」字符倒退。在你的例子中,正則表達式看到第一個#,並注意到#沒有參與模式的任何其他部分,開始匹配下一個標記(在你的情況下爲.+?)。它會這樣做,直到它遇到冒號,然後匹配下一個令牌(再次,.+?)。由於它是從左到右,它會匹配到第一個散列,然後停止,因爲它是懶惰的。

這其實是一個普遍的誤解 - 對?修改的量詞是不是非貪婪,這是。它將匹配最小可能的字符串,從左到右

要修復原來的正則表達式,你可以修改它是這樣的:

/.+#(.+?):(.+?)#/im 

這是什麼會做的是冒號前的最後一個散列之前使用一個貪婪的比賽,迫使第一捕獲組到僅使用散列和冒號之間的東西。本着同樣的精神,這個小組將不需要懶惰修改或者,產生最終的正則表達式:

/.+#(.+):(.+?)#/im 
+0

感謝您發現非貪婪/懶惰的差異。放這樣的話真的很有意義。 – Radacina

+1

@Radacina:如果答案是有用的,通常在SO上,使用投票箭頭旁邊的複選標記按鈕將其標記爲您的問題的答案。這有助於其他人找到他們問題的答案,因爲那樣他們就不必在問題的整個答案部分尋找答案。 –

1

捕獲組1正在尋找#然後任何東西(不包括新行)直到第一個:。所以partB#partC是有道理的。

你的修飾符也沒有做任何事情。您沒有區分大小寫的字母,而且您沒有使用錨點。

你可以看到你的正則表達式在這裏如何處理https://regex101.com/r/iS0lW9/1

+0

是的,我現在明白爲什麼它像這樣對待它,它是有道理的。感謝修改器的註釋。 – Radacina