Possible Duplicate:
String.replaceAll() anomaly with greedy quantifiers in regex
I was writing code that uses Matcher#replaceAll
and found following result highly confusing:
Pattern.compile("(.*)").matcher("sample").replaceAll("$1abc");
Now, I would expect the output to be sampleabc
but Java throws at me sampleabcabc
.
Does anybody have any ideas why?
Now, sure, when I anchor the pattern (^(.*)$
) the issue goes away. Still I don't know why the hell would replaceAll
do a double replacement like that.
And to add insult to injury, following code:
Pattern.compile("(.*)").matcher("sample").replaceFirst("$1abc")
works as expected, returning just sampleabc
.
It looks like it's matching the empty string at the end of the input, for some reason. (I can see why it would match; I'm intrigued that it matches once and only once.)
If you change replaceAll("$1abc")
to replaceAll("'$1'abc")
the result is 'sample'abc''abc
.
Note that if you change (.*)
to (.+)
then it works correctly, because it has to match at least one character.
The diagnosis is confirmed by this code:
Matcher matcher = Pattern.compile("(.*)").matcher("sample");
while (matcher.find()) {
System.out.printf("%d to %d\r\n",
matcher.start(),
matcher.end());
}
... which outputs:
0 to 6
6 to 6
There are two things going on here that explain why this happens:
(.*)
will successfully match empty strings.So, after the entire string "sample"
is matched, another match is attempted just after the e
. Even though there are no characters left the match succeeds and a second replacement occurs.
Additional replacements do not occur because the regex engine will always move forward. Just after the last character is a valid starting index so the empty string will match once, but after the empty string is matched there are no more valid starting positions for the regex engine to attempt a match from.
As an alternative to adding a beginning of string anchor to your regex, you can modify your regex so it matches one or more character by changing (.*)
to (.+)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With