2011-12-22 11 views

Respuesta

57

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.

+0

De acuerdo. Esto también es cierto para Perl. 'perl -le '$ x =" prueba "; $ x = ~ s /.*/ a/g; imprimir $ x'' produce "aa". –

+7

@ChrisDolan: 'sed' produce solo' a', pero dudo que sea un error. :-) –

+0

@ A.H. sí de hecho ... Tengo que leer "Mastering Regular Expressions" nuevamente – fge

Cuestiones relacionadas