Esto no es una anomalía: .*
puede coincidir con cualquier cosa.
usted pide para reemplazar todas las ocurrencias:
- la primera aparición hace coincidir con toda la cadena, por lo que el motor de expresiones regulares se inicia desde el final de la entrada para el próximo partido;
- pero
.*
también coincide con una cadena vacía! Por lo tanto, coincide con una cadena vacía al final de la entrada y la reemplaza con a
.
Usando .+
vez no va a presentar este problema ya que esta expresión regular no puede coincidir con una cadena vacía (que requiere al menos un carácter para que coincida).
O bien, utilizar .replaceFirst()
para reemplazar sólo la primera aparición:
"test".replaceFirst(".*", "a")
^^^^^^^^^^^^
Ahora, ¿por qué .*
se comporta como lo hace y no coincide más del doble (que teóricamente podría) es una cosa interesante a tener en cuenta . Consulte a continuación:
# Before first run
regex: |.*
input: |whatever
# After first run
regex: .*|
input: whatever|
#before second run
regex: |.*
input: whatever|
#after second run: since .* can match an empty string, it it satisfied...
regex: .*|
input: whatever|
# However, this means the regex engine matched an empty input.
# All regex engines, in this situation, will shift
# one character further in the input.
# So, before third run, the situation is:
regex: |.*
input: whatever<|ExhaustionOfInput>
# Nothing can ever match here: out
Tenga en cuenta que, como @ A.H. notas en los comentarios, no todos los motores regex se comportan de esta manera. GNU sed
, por ejemplo, considerará que ha agotado la entrada después de la primera coincidencia.
De acuerdo. Esto también es cierto para Perl. 'perl -le '$ x =" prueba "; $ x = ~ s /.*/ a/g; imprimir $ x'' produce "aa". –
@ChrisDolan: 'sed' produce solo' a', pero dudo que sea un error. :-) –
@ A.H. sí de hecho ... Tengo que leer "Mastering Regular Expressions" nuevamente – fge