2012-06-04 11 views
14

Exactamente qué título pide. Proporcionaré algunos ejemplos mientras explico mi pregunta.¿La mejor manera de almacenar JS Regex capturando grupos en la matriz?

cadena de prueba:

var test = "#foo# #foo# bar #foo#"; 

Say, quiero extraer todo el texto entre # (todos foo s pero no bar).

var matches = test.match(/#(.*?)#/g); 

Usando .match que el anterior, que va a almacenar todos los partidos, pero que simplemente va a tirar los grupos de captura que parece.

var matches2 = /#(.*?)#/g.exec(test); 

El método .exec aparentemente sólo devuelve cadena coincidente del primer resultado en la posición 0 de la matriz y mi único grupo de captura de ese partido en la posición 1.

He agotado SO, Google y MDN en busca de una respuesta en vano.

Entonces, mi pregunta es, ¿hay alguna forma mejor de almacenar solo los grupos de captura coincidentes que recorrerlo con .exec y llamar al array.push para almacenar los grupos capturados?

Mi gama esperada para la prueba anterior debe ser: se aceptan

[0] => (string) foo 
[1] => (string) foo 
[2] => (string) foo 

Pure respuestas JS y jQuery, galletas extra si publican jsFiddle con console.log. =]

Respuesta

14

Puede utilizar .exec también como seguir para construir una matriz

var arr = [], 
    s = "#foo# #bar# #test#", 
    re = /#(.*?)#/g, 
    item; 

while (item = re.exec(s)) 
    arr.push(item[1]); 

alert(arr.join(' '));​ 

Working Fiddle

encuentra desde Here

Bueno, todavía tiene un bucle, si no quieres un bucle entonces piensa que tiene que ir con .replace(). En cuyo caso, el código será como

var arr = []; 
var str = "#foo# #bar# #test#" 
str.replace(/#(.*?)#/g, function(s, match) { 
          arr.push(match); 
         }); 

Comprobar estas líneas de MDN DOC lo que explica su pregunta sobre cómo exec actualizaciones lastIndex propiedad pienso,

Si su expresión regular utiliza la "g" de la bandera, puede usar el método exec varias veces para buscar coincidencias sucesivas en la misma cadena.

Al hacerlo, la búsqueda comienza en la subcadena de str especificada por la propiedad lastIndex de la expresión regular (la prueba también avanzará a la propiedad lastIndex).

+0

Similar al bucle '.exec' que encontré pero mucho más simplificado y elegante, parece una respuesta adecuada, ya que puedo acceder a todas las coincidencias y capturar grupos de la matriz' item'. –

+0

Si desea ver más js magics, puede verificar las respuestas de [am-not-i-am] (http://stackoverflow.com/users/1106925/am-not-i-am), es de una de su respuesta. :) –

+0

Preferido su perfil para leer las respuestas más tarde =] Ahora, incluso después de leer la [Documentación de MDN] (https://developer.mozilla.org/es/JavaScript/Reference/Global_Objects/RegExp/exec) no pude ¿Cómo funciona '.exec' sabe desde dónde empezar a coincidir en la cadena (el" desplazamiento "?) cada vez que se invoca, bueno, importante es que funciona. Creo que almacena automáticamente la propiedad 'lastIndex' Si alguien puede contribuir con un comentario, por favor hazlo. =] –

4

No estoy seguro si esto es la respuesta que está buscando, pero usted puede intentar el siguiente código:

var matches = []; 
 

 
var test = "#foo# #foo# bar #foo#"; 
 

 
test.replace(/#(.*?)#/g, function (string, match) { 
 
    matches.push(match); 
 
}); 
 

 
alert(JSON.stringify(matches));

espero que ayude.

+0

Usando '.replace' para aprovechar el modificador global, un truco realmente dulce (mejor que repetirlo con' .exec', que era la pregunta). Voy a +1 por el momento y acepto antes de irme a dormir si no hay una mejor opción (manteniendo esta pregunta abierta por un tiempo, ya que podría ser útil para futuras referencias). =] –

0

Otro pensamiento, aunque ejecutivo es igual de eficiente.

var s= "#foo# #foo# bar #foo#"; 
s= s.match(/#([^#])*#/g).join('#').replace(/^#+|#+$/g, '').split(/#+/); 
2

data.replace(/.*?#(.*?#)/g, '$1').split(/#/)
No hay bucles, no hay funciones.

+0

Además, el resultado incorrecto. Esperado '[" foo "," foo "," foo "]'. Actual '[" foo "," foo "," foo "," "]'. –

+0

@AaditMShah Sí, eso es un inconveniente: siempre tendrías que sacar el extra. Bien descrito. – Leonid

0

En caso de que alguien llegue con una necesidad similar a la mía, necesitaba una función correspondiente para un controlador de configuración URL de estilo Django que pudiera pasar "argumentos" de ruta a un controlador. Se me ocurrió esto. Naturalmente, no funcionaría muy bien si se combinara con '$', pero no se rompería con '$ 1,00'. Es un poco más explícito de lo necesario. Podrías simplemente devolver los grupos coincidentes de la instrucción else y no molestarte con la prueba for loop sino ;; en el medio de una declaración de bucle asusta a la gente a veces.

var url = 'http://www.somesite.com/calendar/2014/june/6/'; 
var calendarMatch = /^http\:\/\/[^\/]*\/calendar\/(\d*)\/(\w*)\/(\d{1,2})\/$/; 

function getMatches(str, matcher){ 
    var matchedGroups = []; 
    for(var i=1,groupFail=false;groupFail===false;i++){ 
     var group = str.replace(matcher,'$'+i); 

     groupFailTester = new RegExp('^\\$'+i+'$'); 

     if(!groupFailTester.test(group)){ 
      matchedGroups.push(group); 
     } 
     else { 
      groupFail = true; 
     } 
    } 
    return matchedGroups; 
} 

console.log(getMatches(url, calendarMatch)); 
Cuestiones relacionadas