Почему preg_replace с/(.*)/повторяет часть строки?

Почему следующий код:

<?php echo preg_replace("/(.*)/", "$1.def", "abc");

Вывод abc.def.def вместо abc.def?

Мне интересно понять, почему происходит повторение.

Использование /(.+)/ или /^(.*)$/ работает так, как ожидалось, но я не ищу решение, просто задавая вопрос (хотя эти шаблоны могут быть связаны с ответом).

Tinker с живой версией здесь.

Ответы

Ответ 1

Потому что .* соответствует пустой подстроке в конце строки. Это означает, что в строке abc есть два совпадения:

  • Вся строка abcabc.def
  • Пустая строка → .def

который дает abc.def.def.


Изменить: Подробно о том, почему это происходит, объясняется в аномалии String.replaceAll() с жадными квантификаторами в regexя > .

Ответ 2

Ожидаемое поведение: https://bugs.php.net/bug.php?id=53855

Это ожидаемое поведение и ничего особенного для PHP. * квантификатор допускает "пустую" совпадение в конце вашего строка темы.

Ответ 3

Если ваше регулярное выражение не жадное, /(.*?)/, вы можете увидеть, как весь процесс повторения работает в гораздо большем/заметном масштабе:

.defa.defb.defc.def

Вы получаете четыре матча: a, b, c, empty. В то время как, как говорили другие люди, с жадным регулярным выражением вы получаете 2 совпадения, полную строку и пустую строку.