2009-05-09 18 views
60

¿Por qué las subclases de Javascript dejan de funcionar cuando se establece el modificador g?JavaScript expresiones regulares y subclases

var text = 'test test test test'; 

var result = text.match(/t(e)(s)t/); 
// Result: ["test", "e", "s"] 

lo anterior funciona bien, es result[1]"e" y result[2] es "s".

var result = text.match(/t(e)(s)t/g); 
// Result: ["test", "test", "test", "test"] 

Lo anterior ignora mis grupos de captura. ¿La siguiente es la única solución válida?

var result = text.match(/test/g); 
for (var i in result) { 
    console.log(result[i].match(/t(e)(s)t/)); 
} 
/* Result: 
["test", "e", "s"] 
["test", "e", "s"] 
["test", "e", "s"] 
["test", "e", "s"] 
*/ 

Respuesta

91

Usando String 's match() función no volverá grupos capturado si se establece el modificador mundial, como lo encontró a cabo.

En este caso, querrá usar un objeto RegExp y llamar a su función exec(). String 's match() es casi idéntica a RegExp' s exec() función ... excepto en casos como estos. Si se establece el modificador global, la función normal match() no devolverá los grupos capturados, mientras que la función RegExpexec() sí lo hará. (Conocido here, entre otros lugares.)

Otra captura de recordar es que exec() no devuelve los partidos en una gran variedad partidos-continúa repitiéndose hasta que se agote, en cuyo caso se vuelve null.

Así, por ejemplo, se podría hacer algo como esto:

var pattern = /t(e)(s)t/g; // Alternatively, "new RegExp('t(e)(s)t', 'g');" 
var match;  

while (match = pattern.exec(text)) { 
    // Do something with the match (["test", "e", "s"]) here... 
} 

Otra cosa a destacar es que RegExp.prototype.exec() y RegExp.prototype.test() ejecutar la expresión regular en la cadena entregada y regresar el primer resultado. Cada llamada secuencial pasará por el conjunto de resultados actualizando RegExp.prototype.lastIndex en función de la posición actual en la cadena.

Aquí hay un ejemplo: // Recuerde que hay 4 coincidencias en el ejemplo y el patrón. lastIndex comienza en 0

pattern.test(text); // pattern.lastIndex = 4 
pattern.test(text); // pattern.lastIndex = 9 
pattern.exec(text); // pattern.lastIndex = 14 
pattern.exec(text); // pattern.lastIndex = 19 

// if we were to call pattern.exec(text) again it would return null and reset the pattern.lastIndex to 0 
while (var match = pattern.exec(text)) { 
    // never gets run because we already traversed the string 
    console.log(match); 
} 

pattern.test(text); // pattern.lastIndex = 4 
pattern.test(text); // pattern.lastIndex = 9 

// however we can reset the lastIndex and it will give us the ability to traverse the string from the start again or any specific position in the string 
pattern.lastIndex = 0; 

while (var match = pattern.exec(text)) { 
    // outputs all matches 
    console.log(match); 
} 

Puede encontrar información sobre cómo utilizar objetos RegExpon the MDN (en concreto, aquí está la documentación para the exec() function).

+3

usando exec no parece escuchar el modificador g, pero admite subclases/grupos. Entonces, el resultado sería la primera coincidencia (básicamente ignora el modificador g) –

+0

Agregó una aclaración al respecto: debe llamar a exec() repetidamente para obtener las coincidencias múltiples. – hbw

+2

No es la solución más elegante. que estaba esperando una salida algo como esto: [ \t [ "prueba", "e", "s"], \t [ "prueba", "e", "s"], \t [" prueba "," e "," s "], \t [" prueba "," e "," s "] ] –

Cuestiones relacionadas