2011-02-09 2 views
12

Un simple script de prueba:expresiones regulares en javascript falla cada otra vez con el aporte idéntica

<script type="text/javascript"> 
    var reg = new RegExp('#([a-f0-9]{3})$', 'gi'); 
    for (var i = 0; i < 10; i++) { 
     console.log(reg.exec('#fff')); 
    } 
</script> 

salida de la consola:

["#fff", "fff"] 
null 
["#fff", "fff"] 
null 
["#fff", "fff"] 
null 
["#fff", "fff"] 
null 
["#fff", "fff"] 
null 

¿Por qué todos los demás nulo resultado cuando la entrada se mantiene constante?

+0

$ ancla el patrón al final de la línea. Sin eso, algo como '#fff blah blah blah' también coincidiría. Por supuesto, en este momento, la expresión regular coincidirá con 'blah blah blah # fff', ya que no está anclada al inicio de la línea con'^' –

Respuesta

29

Cuando se utiliza el indicador global, la expresión regular se convierte en "pegajosa". Es decir, utiliza una variable de contador para rastrear donde se encontró la última coincidencia. En lugar de coincidir desde el principio cada vez, una expresión regular adhesiva en realidad retomará donde terminó el último partido. Este contador solo se reiniciará de nuevo a 0 (el comienzo) si falla la coincidencia completa (razón por la cual funciona en cualquier otro momento)

En su caso, mi sugerencia sería soltar el indicador g.

Para más información: RegExp @ MDC

+1

No sabía que ... vives y aprendes: D –

3

Su problema es la "gi" en el segundo argumento, sólo se lo quitó y se prueban en la consola Chrome:

var reg = new RegExp('#([a-f0-9]{3})$'); 
9

Matt ha respondido por qué. Sólo quería añadir que se puede ver esto comprobando el valor de lastIndex en el objeto RegExp antes y después de la llamada exec

var reg = new RegExp('#([a-f0-9]{3})$', 'gi'); 
for (var i = 0; i < 10; i++) { 
    console.log(reg.lastIndex); 
    console.log(reg.exec('#fff')); 
    console.log(reg.lastIndex); 
} 

salida es

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

undefined 

lo que demuestra que en cada otra iteración de la loop, la coincidencia de expresiones regulares comienza desde donde terminó el lastIndex. Puede establecer lastIndex en 0 antes de cada exec llamada o soltar la bandera por completo.

1

encontré esto en la web ...

Llamar a la función exec() también cambia la propiedad lastIndex del objeto RegExp .
Almacena el índice en la cadena de asunto en la que comenzará el próximo intento de coincidencia.
Puede modificar este valor para cambiar la posición de inicio de la próxima llamada al exec().

El comportamiento que describes indica que el objeto RegExp tiene un estado que se ha modificado mediante una llamada al método exec().

Creo que necesita modificar la propiedad lastindex antes de volver a ejecutar el método exec.
más información aquí: Javascript Regexp Object

Cuestiones relacionadas