2013-05-19 145 views
6

我有一個.net正則表達式,我正在使用Windows Powershell進行測試。輸出如下:非貪婪的正則表達式給出了貪婪的結果

> [System.Text.RegularExpressions.Regex]::Match("aaa aaa bbb", "aaa.*?bbb") 


Groups : {aaa aaa bbb} 
Success : True 
Captures : {aaa aaa bbb} 
Index : 0 
Length : 11 
Value : aaa aaa bbb 

我的期望是,使用?量詞將導致匹配是aaa bbb,作爲一個的第二組是足以滿足的表達。我對非貪婪量詞是否有缺陷有所瞭解,還是我的測試不正確?

注:這顯然是不一樣的問題,因爲Regular Expression nongreedy is greedy

回答

5

這是一個常見的誤解。懶惰量詞不保證儘可能短的匹配。他們只確保當前位置的當前量詞不匹配比整體匹配所需字符多的字符。

如果你真的想確保儘可能最短的匹配,你需要明確。在這種情況下,這意味着代替.*?,您需要一個subregex,該匹配項既不是aaa也不是bbb。由此產生的正則表達式因此將是

aaa(?:(?!aaa|bbb).)*bbb 
+0

我剛剛做了我應該做的第一件事,並諮詢了Friedl的相關章節。這導致我成爲'aaa((!!aaa)。)* bbb',這與你所說的差不多,除了你的答案有添加的細節使得子表達式無法捕獲並且還測試了bbb中的負數展望。很好的答案。 –

5

比較結果的字符串aaa aaa bbb bbb

regex: aaa.*?bbb 
result: aaa aaa bbb 

regex: aaa.*bbb 
result: aaa aaa bbb bbb 

正則表達式引擎找到的aaa第一次出現,然後跳過所有字符(.*?)直到第一個發生bbb,但對於貪婪算子(.*)它會繼續找到更大的結果,因此匹配las t發生bbb

+0

這是最清楚的解釋發生了什麼。 +1 – duozmo

0

那麼它真的很簡單,我們有以下字符串

AAA AAA BBB

讓我們來看看,我們有這個表達式aaa.*?bbb。正則表達式引擎將與aaa

AAA AAA BBB

正則表達式引擎現在已經開始.*?bbb。它將繼續與space

AAA 空間 AAA BBB

但我們仍然有一些字符,直到bbb?所以,正則表達式引擎將繼續它的方式和第二盤比賽一

AAA AAA空間 BBB

的最後的正則表達式引擎將匹配bbb

AAA AAA bbb


讓我們看看,如果我們只想匹配第二aaa我們可以使用下面的正則表達式:

(?<!^)aaa.*?bbb,這意味着匹配aaa是不是在句子的開頭。

我們也可能使用aaa(?= bbb).*?bbb,這意味着要匹配aaa,其次是space bbb

看到它的工作1 - 2

剛來我的感覺,但爲什麼不直接使用aaa bbb

1

這不是一個貪婪/懶惰的問題。問題在於你的字符串是從左到右分析的。當匹配第一個aaa時,正則表達式引擎逐個添加字符以具有完整模式。

請注意,在您的示例中,您會得到相同的結果:匹配第一個aaa,正則表達式引擎會逐個字符地取回所有最後的字符並回溯,直到完成匹配。