Regexp metachars“*”和“*?”在JAVA中,replaceAll()方法表现得很奇怪

时间:2013-02-04 17:13:22

标签: java regex string replace

  

可能重复:
  String.replaceAll() anomaly with greedy quantifiers in regex
  Strange behavior in regexes

虽然

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

全部返回b,为什么

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

返回bb

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

返回bab

3 个答案:

答案 0 :(得分:22)

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

首先将a替换为b,然后将指针推进b。然后它匹配字符串的结尾,并替换为b。由于它匹配一个空字符串,它会使指针前进,掉出字符串并完成,从而产生bb

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

首先匹配字符串的开头并替换为b。它与a不符,因为?中的a*?表示“非贪婪”(匹配尽可能少)。由于它匹配一个空字符串,它会使指针前进,跳过a。然后它匹配字符串的结尾,替换为b并从字符串中删除,从而生成bab。最终结果与您"a".replaceAll("", "b")的结果相同。

答案 1 :(得分:5)

这是因为零宽度匹配。


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

将匹配两次:

  1. 在字符串开头尝试匹配,贪婪*使用a作为匹配。
  2. 前进到字符串中的下一个位置(现在在字符串的末尾),尝试匹配,空字符串匹配。

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

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

    也会两次匹配:

    1. 在字符串开头尝试匹配,非贪婪的*?与空字符串匹配而不消耗a
    2. 前进到字符串中的下一个位置(现在在字符串的末尾),尝试匹配,空字符串匹配。

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

答案 2 :(得分: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