2016-07-26 233 views
2

給下面的代碼:
Perl的貪婪正則表達式不是演戲貪婪

use strict; 
use warnings; 

my $text = "asdf(blablabla)"; 

$text =~ s/(.*?)\((.*)\)/$2/; 
print "\nfirst match: $1"; 
print "\nsecond match: $2"; 

我預計$2會趕上我的最後一個支架,但我的輸出是:
enter image description here
如果.*默認情況下它是貪婪的,爲什麼它停在支架上?

+4

你實際上在模式中定義了它:')'(與'\)匹配')必須在組2外。 –

+1

'。*?'是** lazy **! – Jan

+0

@Jan你是在誤解我的問題,我是在談論第二個'。*' –

回答

4

.*是一個貪婪的子模式,但它沒有考慮分組。分組使用一對非轉義的括號來定義(請參閱Use Parentheses for Grouping and Capturing)。

看到您的組界限是:

s/(.*?)\((.*)\)/$2/ 
    | G1| |G2| 

所以,無論$1也不$2\(\)匹配()外,並不會一部分。

如果需要)$2一部分,使用

s/(.*?)\((.*\))/$2/ 
      ^

一個正則表達式引擎在處理這兩個字符串,由左到右的模式。第一個(.*?)首先被處理,並且匹配到第一個字面(符號,因爲它是懶惰的(在可以返回有效匹配之前匹配儘可能少的字符),並且將(之前的整個部分放入第1組堆棧。然後,(匹配但未捕獲,然後(.*)匹配除換行符以外的任何0+字符,直到最後一個)符號,並將捕獲放入組2.然後,)剛剛匹配。關鍵是.*抓住了整個字符串,但隨後發生了回溯,因爲引擎試圖適應模式中的最終))必須匹配,但未在您的模式中捕獲,因此,由於組邊界位置,它不屬於組2。你可以看到正則表達式調試器this regex demo page查看模式如何匹配你的字符串。

+0

如果我錯了,請糾正我,所以當搜索一個模式時,它將首先嚐試在分組之外尋找「事物」,然後搜索在由外部規則劃定的文本中? –

+0

在這種情況下,它搜索括號,找到它們,然後在括號內的文本中搜索'。*',對嗎? –

+1

這是不對的。我將解釋添加到答案中。 –