2013-02-04 65 views
18

可能重複:
String.replaceAll() anomaly with greedy quantifiers in regex
Strange behavior in regexes正則表達式metachars「*」和「*?」在Java的的replaceAll()方法,行爲古怪

雖然

"a".replaceAll("a", "b") 
"a".replaceAll("a+", "b") 
"a".replaceAll("a+?", "b") 

都返回b,爲什麼

"a".replaceAll("a*", "b") 

回報bb

"a".replaceAll("a*?", "b") 

回報bab

+0

對重複還在尋找...... – Bergi

+2

@Bergi我也是... – sp00m

+3

這裏你去:http://stackoverflow.com/qu estions/9228509 /奇怪的行爲在正則表達式 – Matthew

回答

22
"a".replaceAll("a*", "b") 

首先替換ab,然後推進指針過去b。然後它匹配字符串的結尾,並替換爲b。由於它匹配了一個空字符串,它會前進指針,脫離字符串並結束,導致bb

"a".replaceAll("a*?", "b") 

首先匹配字符串的開頭並用b代替。它與a不匹配,因爲?在表示「非貪婪」(儘可能少匹配)。由於它匹配了一個空字符串,所以它前進指針,跳過a。然後它匹配字符串的結尾,替換爲b並脫離字符串,導致bab。最終結果與"a".replaceAll("", "b")相同。

+0

這是一個錯誤,對不對? – mikeslattery

+0

@mikeslattery如果指針沒有前進,那麼只要您匹配空字符串,替換者就會陷入無限循環。 –

+0

打印bbb。這對我來說似乎更合乎邏輯: echo a | perl -i -pe「s/a *?/ b/g」 – jdb

5

發生這種情況是因爲零寬度匹配。


"a".replaceAll("a*", "b") 

將匹配兩次:在字符串的開頭

  1. 嘗試匹配,貪婪*消耗a作爲搭配。
  2. 前進到字符串中的下一個位置(現在位於字符串末尾),嘗試匹配那裏,空字符串匹配。

    " a " 
    \| \___ 2. match empty string 
        \_____ 1. match "a" 
    


"a".replaceAll("a*?", "b") 

也將匹配兩次:在字符串的開頭

  1. 嘗試匹配,非貪婪*?空字符串匹配不消耗a
  2. 前進到字符串中的下一個位置(現在在字符串末尾),嘗試匹配那裏,空字符串匹配。

    " a " 
    \ \___ 2. match empty string 
        \_____ 1. match empty string 
    
+1

我喜歡圖表';-)' –

1

"a".replaceAll("a*", "b")

* - for 0 or more so here in `a*`
1. a - replaced by b 
2. * - is also true as empty string is true for *,so, replaced by b 

"a".replaceAll("a*?", "b")

1. *? - makes anything non-greedy means it makes regrex to match as little 
     as possible, 
2. so,the pre and post empty string would be replaced by "b" and 
    as a*? is non-greedy, it will not replace it 
相關問題