paquete
Realmente me estoy volviendo loco por esto y ya he pasado una cantidad desproporcionada de tiempo tratando de averiguar qué está pasando aquí. Así que por favor dame una mano =)
Necesito hacer algunas coincidencias RegExp de cadenas en JavaScript. Desafortunadamente se comporta de manera muy extraña. Este código:
var rx = /(cat|dog)/gi;
var w = new Array("I have a cat and a dog too.", "There once was a dog and a cat.", "I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.");
for (var i in w) {
var m = null;
m = rx.exec(w[i]);
if(m){
document.writeln("<pre>" + i + "\nINPUT: " + w[i] + "\nMATCHES: " + m.slice(1) + "</pre>");
}else{
document.writeln("<pre>" + i + "\n'" + w[i] + "' FAILED.</pre>");
}
}
Devuelve “gato” y “perro” para los dos primeros elementos, como debería ser, pero luego algunos exec()
-las llamadas comienzan a regresar null
. no entiendo porque
publiqué un violín aquídonde puede ejecutar y editar el código.
Y hasta ahora he probado esto en Chrome y Firefox.
Oh aqui está. Debido a que está definiendo su expresión regular global, coincide primero cat
y en el segundo paso del ciclo dog
. Entonces, básicamente solo necesita restablecer su expresión regular (su puntero interno) también. Cf. este:
var w = new Array("I have a cat and a dog too.", "I have a cat and a dog too.", "I have a cat and a dog too.", "I have a cat and a dog too.");
for (var i in w) {
var rx = /(cat|dog)/gi;
var m = null;
m = rx.exec(w[i]);
if(m){
document.writeln("<p>" + i + "<br/>INPUT: " + w[i] + "<br/>MATCHES: " + w[i].length + "</p>");
}else{
document.writeln("<p><b>" + i + "<br/>'" + w[i] + "' FAILED.</b><br/>" + w[i].length + "</p>");
}
document.writeln(m);
}
-
Woh- “puntero interno de una expresión regular”? ¿Podría recomendar un recurso sobre eso? ¡Gracias!
– kater louis
14/01/2019 a las 15:00
-
Guau… He estado escribiendo JavaScript intensamente durante los últimos 14 años, y
RexExp
s más y más intensamente durante los últimos 8 años, y esto me sorprende bastante. ¿Tendría una mejor comprensión de esto si fuera mejor en Perl?– Cody
20 de octubre de 2021 a las 2:14
-
Te daría 1000 votos si pudiera. Eso me ahorró horas y me dejó boquiabierto.
– Steinroe
1 abr a las 8:47
El objeto regex tiene una propiedad lastIndex
que se actualiza cuando se ejecuta exec
. Entonces, cuando ejecuta la expresión regular en, por ejemplo, “Tengo un gato y un perro también”, lastIndex
está establecido en 12. La próxima vez que ejecute exec
en el mismo objeto regex, comienza a buscar desde el índice 12. Por lo tanto, debe restablecer el lastIndex
propiedad entre cada corrida.
-
¡Gracias por la explicación! Ayuda mucho configurando
myRe.lastIndex = 0;
para uso posterior.– Antonio
20 de enero de 2013 a las 1:52
-
Creo que esta debería ser la respuesta correcta porque sigue la mejor práctica de reutilizar el mismo objeto regex
– Pitufo
18 de marzo de 2019 a las 20:17
-
De acuerdo, esta debería ser la respuesta correcta. Reutiliza el mismo objeto regex y también explica la mecánica interna. OP debería considerar cambiar.
– Sean Coley
16 dic 2019 a las 16:30
Dos cosas:
- La mencionada necesidad de Reiniciar al usar el
g
bandera (mundial). Para resolver esto, recomiendo simplemente asignar0
hacialastIndex
miembro deRegExp
objeto. Esto tiene un mejor rendimiento que destruir y recrear. - Ten cuidado cuando usar
in
palabra clave para caminar unArray
objeto, porque puede dar lugar a resultados inesperados con algunas librerías. A veces deberías consultar con algo comoisNaN(i)
o si sabe que no tiene agujeros, use el bucle for clásico.
El código puede ser:
var rx = /(cat|dog)/gi;
w = ["I have a cat and a dog too.", "There once was a dog and a cat.", "I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat."];
for (var i in w)
if(!isNaN(i)) // Optional, check it is an element if Array could have some odd members.
{
var m = null;
m = rx.exec(w[i]); // Run
rx.lastIndex = 0; // Reset
if(m)
{
document.writeln("<pre>" + i + "\nINPUT: " + w[i] + "\nMATCHES: " + m.slice(1) + "</pre>");
} else {
document.writeln("<pre>" + i + "\n'" + w[i] + "' FAILED.</pre>");
}
}
-
Esta debería ser la respuesta correcta. Ajuste
rx.lastIndex = 0
es mucho mejor que volver a crear el objeto RegEx dentro del ciclo.– Minoru
25 sep 2019 a las 19:27
-
Aún así, sería mejor simplemente no usar el
g
marca cuando no lo quieras. No tiene sentido crear una expresión regular que actualice específicamentelastIndex
solo para restablecerlo después de cada ejecución.– Roberto
8 de agosto de 2021 a las 19:44
-
Es posible que desee buscar globalmente en un elemento y luego restablecer y reutilizar la expresión regular en el siguiente. Creo que el código OP es solo un ejemplo para mostrar lo que no entiende.
– ESL
3 sep 2021 a las 19:16
Tuve un problema similar usando solo /g, y la solución propuesta aquí no funcionó para mí en FireFox 3.6.8. Tengo mi script trabajando con
var myRegex = new RegExp("my string", "g");
Estoy agregando esto en caso de que alguien más tenga el mismo problema que tuve con la solución anterior.
falla solo en un
"I have a cat and a dog too."
parece– Fantasma silencioso
18 de enero de 2011 a las 13:48
exec devuelve nulo si una coincidencia falla por diseño, por lo que, por alguna razón, no coincide.
– Martín Jespersen
18 de enero de 2011 a las 13:49