emparejar Vs exec en JavaScript [duplicate]

5 minutos de lectura

Necesito alguna aclaración para Match Vs exec en JavaScript; aqui alguien dice eso

“exec con una expresión regular global está destinado a usarse en un bucle” pero antes que nada, como ves en mi ejemplo, este no es el caso; en mi ejemplo, exec con expresión regular global está devolviendo todas las coincidencias en una matriz. En segundo lugar, dicen que para String.match devuelve todas las coincidencias sin necesidad de recorrerlas. Pero, de nuevo, eso no sucede en mi ejemplo y solo devuelve la cadena de entrada. ¿He entendido mal/he hecho algo mal?

var myString = "[22].[44].[33].";
var myRegexp = /.*\[(\d*)*\].*\[(\d*)*\].*\[(\d*)*\].*/g;

var execResult = myRegexp.exec(myString);
console.log(execResult.length);
console.log(execResult[1]);// returns 22 and execResult has all of my matches from index 1 to the length of array


var matchResult = myString.match(myRegexp);
console.log(matchResult.length);
console.log(matchResult);// returns just myString which is "[22].[44].[33]."! Why is that?

avatar de usuario de thefourtheye
los cuatro ojos

  1. string.match encuentra la primera coincidencia y la devuelve con la coincidencia real, el índice en el que se encontró el texto y la entrada real, cuando no se utiliza la bandera global.

  2. string.match solo devuelve todos los partidos, cuando se utiliza la bandera global.

var myString = "[22].[44].[33].";
    
console.log(myString.match(/\d+/)); 
// [ '22', index: 1, input: '[22].[44].[33].' ]
console.log(myString.match(/\d+/g));
// [ '22', '44', '33' ]

La principal diferencia entre string.match y regex.exec es el regex el objeto se actualizará de la coincidencia actual con regex.exec llamar. Por ejemplo,

var myString = "[22].[44].[33].", myRegexp = /\d+/g, result;

while (result = myRegexp.exec(myString)) {
    console.log(result, myRegexp.lastIndex);
}

regresará

[ '22', index: 1, input: '[22].[44].[33].' ] 3
[ '44', index: 6, input: '[22].[44].[33].' ] 8
[ '33', index: 11, input: '[22].[44].[33].' ] 13

Como puedes ver, el lastIndex La propiedad se actualiza cada vez que se encuentra una coincidencia. Por lo tanto, tenga en cuenta dos cosas cuando utilice execo te encontrarás con un bucle infinito.

  1. si no usas g opción, entonces siempre obtendrá la primera coincidencia, si hay una, de lo contrario null. Entonces, lo siguiente se ejecutará en un ciclo infinito.

    var myString = "[22].[44].[33].", myRegexp = /\d+/, result;
    
    while (result = myRegexp.exec(myString)) {
        console.log(result, myRegexp.lastIndex);
    }
    
  2. No olvide usar el mismo objeto de expresión regular con llamadas posteriores. Porque, el objeto regex se actualiza cada vez, y si pasa un nuevo objeto, nuevamente el programa se ejecutará en un bucle infinito.

    var myString = "[22].[44].[33].", result;
    
    while (result = /\d+/g.exec(myString)) {
        console.log(result);
    }
    

Avatar de usuario de Redu
Reducir

String.prototype.match() y RegExp.prototype.exec() son similares tanto para encontrar múltiples ocurrencias como para devolverlas en una matriz. Sin embargo, el método exec devuelve una matriz de información más detallada. Por ejemplo, a diferencia de Match, también puede encontrar múltiples ocurrencias de los grupos de captura. Entonces, si tiene grupos de captura, exec es esencial. Una cosa a tener en cuenta cuando se trabaja con exec no debe invocarse desde una expresión regular literal. Primero asigne su expresión regular a una variable y utilícela para llamar a su método exec. Otra cosa es que, mientras que la coincidencia traería múltiples ocurrencias en una matriz de elementos a la vez, con exec debe iterar para que se capture cada ocurrencia.

Invocar match es bastante simple. Dado que es un método de prototipo de cadena, simplemente lo encadena a una cadena y proporciona una expresión regular como argumento para el método de coincidencia como; “test”.match(/es/) Se puede usar una representación literal de una expresión regular sin problema.

Invocar a exec es más complicado. Como mencioné anteriormente, es mejor tener la expresión regular asignada a algo previamente. bueno veamos un ejemplo

var text="["job name 1","nat 1"],["job name 2","nat 2"],["job name 3","nat 3"]",
     reg = /([^"]+)","([^"]+)/g,
      tm = [],
      te = [];

tm = text.match(reg); // tm has result of match
while(te[te.length]=reg.exec(text)); // te has result of exec + an extra null item at the end
te.length--; // te normalized.

document.write("<pre>" + JSON.stringify(tm,null,2) + "</pre>\n");
document.write("<pre>" + JSON.stringify(te,null,2) + "</pre>\n");

Como puede ver, el resultado de exec también incluye los grupos de captura. La forma en que elijo poblar te La matriz es algo poco ortodoxa, pero odio usar una matriz temporal solo en la parte condicional del ciclo while. Esto me parece mucho más ordenado. Lo único es que el nulo final para detener el ciclo while se inserta al final de te formación. De ahí lo siguiente te.length-- instrucción.

Editar: Ahora también está el Cadena.prototipo.matchAll() funcionalidad disponible en los navegadores modernos que en su mayoría elimina la carga de usar exec sobre nuestros hombros. Puede buscar otra respuesta mía para ver eso en acción.

  • Creo que es engañoso decir “Entonces, si tiene grupos de captura, el ejecutivo es esencial”, ya que .match() claramente devuelve una matriz de todos los grupos capturados especificados. Insinúas tanto en tu primera oración y obviamente sabes cómo funciona cada una. Tal vez quiera decir algo más en la línea de “si necesita aplicar recursivamente uno o más grupos de captura, usando la bandera global y .exec() son esenciales”?

    – ballenf

    31 de agosto de 2016 a las 21:32

  • @Ben Fletcher Gracias. Sí, claro, me refería al caso de obtener los grupos de captura cuando se estableció la bandera global. Sin embargo, ahora tenemos la Cadena.prototipo.matchAll() que devuelve un objeto iterador que revela todos los grupos capturados cuando se distribuyen. Mencionado como edición en la respuesta anterior.

    – Redú

    26 de mayo de 2019 a las 12:37


  • @Redu, no entendí esta parte: “Una cosa a tener en cuenta cuando se trabaja con exec no debe invocarse desde una expresión regular literal. Primero asigne su expresión regular a una variable y utilícela para llamar a su método exec desde. ” ¿Por qué exactamente no debería invocarlo desde una expresión regular literal?

    – pb2017

    26 de diciembre de 2022 a las 22:47

  • @bp2017 Puede encontrar el motivo aquí debajo de Advertencia sección en rosa.

    – Redú

    27 de diciembre de 2022 a las 19:02


¿Ha sido útil esta solución?