Проверено экспериментом: совпадение replaceAll не будет совпадать дважды в одной и той же позиции строки без продвижения.
Эксперимент:
System.out.println("foo".replaceAll(".??", "[bar]"));
Выход:
[bar]f[bar]o[bar]o[bar]
Пояснение:
Шаблон .??
- это не жадное совпадение, состоящее из 0 или 1 символа, что означает, что он не будет соответствовать ничему по предпочтению и одному символу, если будет принудительно. На первой итерации он ничего не соответствует, и replaceAll
заменяет ""
на "[bar]"
в начале строки. На второй итерации он снова ничего не будет соответствовать, но это запрещено, поэтому вместо одного символа копируется с ввода на выход ("f"
), позиция продвигается, сравнение повторяется и т. Д. - f - bar - o - bar - o - bar: один «[bar]» для каждого отдельного места, где может быть сопоставлена пустая строка. В конце нет возможности продвинуться, поэтому замена прекращается, но только после , совпадающего с «окончательной» пустой строкой.
Просто ради любопытства Perl делает нечто очень похожее, но применяет правило по-другому, давая вывод "[bar][bar][bar][bar][bar][bar][bar]"
для того же ввода и того же шаблона - .??
по-прежнему запрещено делать нулевую ширину совпадать два раза подряд в одной и той же позиции, но разрешено возвращать и сопоставлять один символ. Это означает, что он заменяет «» на «[bar]», затем заменяет «f» на «[bar]», затем «» на «[bar]», затем «o» на «[bar]» и т. Д. До конца для строки совпадение по нулевой ширине запрещено и дальнейшее совпадение по положительной ширине невозможно.