Regexp metachars "*" и "*?" в методе JAVA replaceAll() ведут себя странно

Возможный дубликат:
String.replaceAll() аномалия с жадными кванторами в regex
Странное поведение в регулярных выражениях

В то время как

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

all return b, почему

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

return bb и

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

return bab?

Ответы

Ответ 1

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

Сначала заменяет a на b, затем продвигает указатель мимо b. Затем он соответствует концу строки и заменяется на b. Поскольку он соответствует пустой строке, он продвигает указатель, выпадает из строки и заканчивается, в результате получается bb.

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

сначала соответствует началу строки и заменяется на b. Он не соответствует a, потому что ? в a*? означает "не жадный" (как можно меньше). Поскольку он соответствует пустой строке, он продвигает указатель, пропуская a. Затем он совпадает с концом строки, заменяется на b и выпадает из строки, в результате получается bab. Конечный результат будет таким же, как если бы вы сделали "a".replaceAll("", "b").

Ответ 2

Это происходит из-за совпадений нулевой ширины.


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

Будет соответствовать два раза:

  • Попробуйте совпадение в начале строки, жадный * потребляет a как совпадение.
  • Перейдите к следующей позиции в строке (теперь в конце строки), попробуйте совпадение там, пустые строки соответствуют.

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


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

Также будет совпадать два раза:

  • Попробуйте совпадение в начале строки, а не жадный *? соответствует пустой строке без использования a.
  • Перейдите к следующей позиции в строке (теперь в конце строки), попробуйте совпадение там, пустые строки соответствуют.

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

Ответ 3

in "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