2011-03-02 18 views
12

Digamos que tenemos el siguiente texto: "1 a, 2 b, 3 c, 4 d" y la siguiente expresión:/\ d (\ w)/giterador expresión JavaScript regular para extraer grupos

lo lo que queremos hacer es extraer a, b, c, d como se denota por la expresión regular.

desgracia "1 a, 2 b, 3 c, 4 d" .match (/ \ d (\ w)/g) producirá una matriz: 1 a, 2 b, 3 c, 4 d y RegExp. $ 1 contendrá solo los grupos del último partido, es decir, RegExp. $ 1 == 'd'.

cómo puedo iterar sobre esta expresión regular para que pueda extraer los grupos, así ... Estoy buscando una solución que es también eficiente de la memoria, es decir, una especie de objeto iterador

EDIT: Se necesita ser genérico Solo estoy brindando un ejemplo simple aquí. Una solución es hacer un ciclo sobre la matriz y volver a aplicar la expresión regular para cada elemento sin la bandera global, pero esta solución me parece un poco estúpida, aunque parece ser la única forma de hacerlo.

+3

Acepte sus preguntas más recientes. – hsz

+1

¿Necesita ser regex? También podría dividir en espacios y comas y extraer de esa manera. – pimvdb

+0

sí, porque estoy proporcionando solo un ejemplo simple ... es más complicado que esto. una solución es volver a aplicar la expresión regular para cada coincidencia en la matriz, pero esto es simplemente estúpido – Pass

Respuesta

12
var myregexp = /\d (\w)/g; 
var match = myregexp.exec(subject); 
while (match != null) { 
    // matched text: match[0] 
    // match start: match.index 
    // capturing group n: match[n] 
    match = myregexp.exec(subject); 
} 

(descaradamente tomado de RegexBuddy)

+0

No me sale esto. match es solo una matriz de todos los elementos como 1 a, 2 b, 3 c, etc. ... no podemos extraer los grupos de captura de esa manera a menos que la regex se vuelva a aplicar o haya API para hacer eso ... – Pass

+0

@Pass - no cuando usted usa 'exex' - match contendrá la coincidencia completa como el primer elemento, y cada grupo como los otros elementos, por ejemplo,' ['1 a', 'a'] ' – Kobi

+0

' match [0] 'es la coincidencia completa ('1 a' por ejemplo); 'match [1]' es el primer grupo de captura ('a'). Esto itera sobre la cadena (vea la última línea del bloque 'while'). –

1

Esto va a trabajar:

"1 a,2 b,3 c,4 d".match(/\w(?:,|$)/g).join(' '); // => "a, b, c, d" 

Si usted tiene una necesidad de repetir:

var r = /\d (\w)/g, 
    s = "1 a,2 b,3 c,4 d", 
    m; 

while (m = r.exec(s)) { 
    // `m` is your match, `m[1]` is the letter 
} 
+0

gracias por la sugerencia, pero el ejemplo es demasiado específico. Estoy buscando una solución genérica porque mi código real hace uso de expresiones regulares más complejas – Pass

+0

@Pass, mira el ciclo. – James

+0

muchas gracias ... esto funciona bien – Pass

2

A más corto, más simple (aunque probablemente menos eficiente) la solución es usar String.prototype.replace. replace es único ya que implícitamente itera sobre todas las coincidencias y ejecuta una función para cada coincidencia. Claro, usted puede usar que funciona para reemplazar el texto en realidad, pero a pesar del nombre de función que no es realmente necesario:

"1 a,2 b,3 c,4 d".replace(/\d (\w)/g, function(complete_match, matched_letter) { 
    console.log(matched_letter); 
}); 

Esto registrará a, b, c, a continuación, d a la consola. (También pasará a volver "undefined,undefined,undefined,undefined", pero no se preocupan por eso aquí.)

más general, el argumento de la función para reemplazar is called with the following parameters:

function(match, p1, p2, [...], offset, string) 
  • match es la subcadena coincidente.
  • p1 etc. son los grupos capturados del partido, si corresponde. Los grupos están en orden del paréntesis de apertura al que corresponden (es decir, el que está más a la izquierda, el primero a los exteriores). Si el grupo coincide con varias subcadenas (es decir, en un escenario (.)+), solo se captura la última subcadena (más a la derecha).
  • offset es el índice de la cadena original de este partido
  • string es la cadena en la que se llamó replace.

La iteración manual es probablemente más eficiente, pero este método no es lento y es más corto y (en mi humilde opinión) más fácil de leer; Tiendo a usar este patrón en un ciclo manual.

Cuestiones relacionadas