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