2012-05-30 23 views
14

¿Por qué el siguiente código:¿Por qué preg_replace con /(.*)/ repite parte de la cadena?

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

salida abc.def.def en lugar de abc.def?

Me interesa saber por qué ocurre la repetición.

El uso de /(.+)/ o /^(.*)$/ funciona como se esperaba, pero no estoy buscando una solución, simplemente haciendo una pregunta (aunque estos patrones pueden estar relacionados con la respuesta).

Tinker con una versión en vivo here.

+0

Caso de prueba más simple - [' Eric

+0

Relacionado: http://stackoverflow.com/questions/8604286/java-regex-anomaly – kennytm

Respuesta

8

Porque .* coincide con la subcadena vacía al final de la cadena. Significa que hay dos coincidencias con la cadena abc:

  1. toda la cadena abcabc.def
  2. La cadena vacía → .def

que da abc.def.def.


Editar: Detalle de por qué sucede se explica en String.replaceAll() anomaly with greedy quantifiers in regex.

+1

¿Por qué no coincide con toda la cadena la primera vez? Si ejecuto '" a ".replace (/.*/," b ")' en javascript, obtengo la 'b' esperada. Si hago 'preg_replace (" /.*/ "," b "," a ")' en php, obtengo 'bb'. – Eric

+2

@Eric: '" a ".replace (/.*/ g," b ")'. – kennytm

+1

Comportamiento extraño. Hubiera pensado que el emparejamiento '. *' Consumiría tanto como fuera posible, incluyendo cualquier cadena vacía al final. ¿No hay una cadena vacía después de esa cadena vacía? :) –

3

Es el comportamiento esperado: Comportamiento https://bugs.php.net/bug.php?id=53855

Se espera y nada peculiar de PHP. El cuantificador * permite que se produzca una coincidencia "vacía" al final de su cadena de asunto .

2

Si usted hace su expresión regular no expansivo, /(.*?)/ se puede ver todo el proceso de repetición de trabajo en una escala mucho más grande/notorio:

.defa.defb.defc.def 

Usted consigue cuatro partidos: a, b, c , empty. Mientras que, como mencionaron otras personas, con una expresión regular codiciosa, obtienes 2 coincidencias, la cadena completa y una cadena vacía.

+0

¿Pero por qué la versión codiciosa no toma todo como una coincidencia, incluida la cadena vacía? – trapper

+0

Porque cuando comienza a coincidir con algo ('abc' en este caso) no puede "agregar" una cadena vacía a una cadena no vacía. Mientras que una vez hecho con la cadena no vacía, ** puede ** hacer coincidir una cadena vacía. – dda

+0

himm ... bueno, eso no tiene ningún sentido para mí jaja – trapper

Cuestiones relacionadas