Tested by experiment: replaceAll's matcher won't match twice in the same string position without advancing.
Experiment:
System.out.println("foo".replaceAll(".??", "[bar]"));
Output:
[bar]f[bar]o[bar]o[bar]
Explanation:
The pattern .??
is a non-greedy match of 0 or 1 characters, which means it will match nothing by preference, and one character if forced to. On the first iteration, it matches nothing, and the replaceAll
replaces ""
with "[bar]"
in the beginning of the string. On the second iteration, it would match nothing again, but that's prohibited, so instead one character is copied from the input to the output ("f"
), the position is advanced, the match is tried again, etc. so you have bar - f - bar - o - bar - o - bar: one "[bar]" for every distinct place where an empty string can be matched. At the end there's no possibility to advance so the replacement terminates, but only after matching the "final" empty string.
Just for curiosity's sake, Perl does something very similar, but it applies the rule differently, giving an output of "[bar][bar][bar][bar][bar][bar][bar]"
for the same input and the same pattern -- .??
is still prohibited from making a zero-width match twice in a row in the same position, but it's allowed to backtrack and match a single character. Meaning it replaces "" with "[bar]", then replaces "f" with "[bar]", then "" with "[bar]" then "o" with "[bar]", etc. until at the end of the string the zero-width match is prohibited and there's no further positive-width match possible.