Квантификатор ?
не позволяет .*
соответствовать как можно меньшему количеству символов, но только большему количеству символов, если это требуется для возврата.
Вот иллюстративный пример использования регулярных выражений для поиска непустого префикса, который также является суффиксом строки (без наложения).
Группа захвата \1
в первом шаблоне является жадной: она сначала сопоставляется со всем и занимает столько же времени, сколько и при возврате. Таким образом, шаблон найдет максимально возможное совпадение префикса / суффикса:
System.out.println(
"abracadabra".replaceAll("^(.+).*\\1$", "($1)")
); // prints "(abra)"
Теперь \1
во втором паттерне неохотно; сначала он ничего не соответствует, и требует больше, поскольку он возвращается. Таким образом, шаблон найдет самое короткое совпадение префикса / суффикса:
System.out.println(
"abracadabra".replaceAll("^(.+?).*\\1$", "($1)")
); // prints "(a)"
В вашем случае .*?
может соответствовать пустой строке, и вам больше не нужно возвращать ее назад и сопоставлять больше, поскольку этого было достаточно для сопоставления всего шаблона.
Смотри также
Вот еще один иллюстративный пример неохотного квантификатора при конечном повторении:
Здесь x{3,5}
является жадным и займет как можно больше.
System.out.println(
"xxxxxxx".replaceAll("x{3,5}", "Y")
); // prints "Yxx"
Здесь x{3,5}?
неохотно и займет как можно меньше.
System.out.println(
"xxxxxxx".replaceAll("x{3,5}?", "Y")
); // prints "YYx"