match Vs exec en JavaScript [dupliquer]

Cette question a déjà une réponse ici:

J'ai besoin de quelques éclaircissements pour match Vs exec en JavaScript; ici quelqu'un dit que

"exec avec une expression régulière est destiné à être utilisé dans une boucle", mais d'abord de tout comme vous le voyez dans mon exemple, ce n'est pas le cas; dans mon exemple, exec avec une expression régulière globale renvoie toutes les correspondances dans un tableau! Deuxièmement, ils disent que pour la chaîne.match il renvoie tous les matchs sans avoir besoin de boucler! Mais encore une fois cela ne se produit pas dans mon exemple et il retourne simplement la chaîne d'entrée? Ai-je mal compris/fait quelque chose de 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?
22
demandé sur Community 2015-01-03 12:04:28

2 réponses

  1. string.match trouve le premier match et le renvoie avec le match, l'indice à partir duquel le texte a été trouvé et l'entrée effective, lorsque l'indicateur n'est pas utilisé.

  2. string.match renvoie simplement toutes les correspondances, lorsque le drapeau global est utilisé.

    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 principale différence entre string.match et regex.exec est le regex objet sera mis à jour de l'actuel match avec regex.exec appeler. Par exemple

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

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

Sera retour

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

Comme vous pouvez le voir, la propriété lastIndex est mise à jour chaque fois qu'une correspondance est trouvée. Donc, garder deux choses à l'esprit lorsque vous utilisez exec, ou , vous allez courir dans une boucle infinie.

  1. Si vous n'utilisez pas l'option g, Vous obtiendrez toujours la première correspondance, s'il y en a une, sinon null. Ainsi, ce qui suit se déroulera dans une boucle infinie.

    var myString = "[22].[44].[33].", myRegexp = /\d+/, result;
    
    while (result = myRegexp.exec(myString)) {
        console.log(result, myRegexp.lastIndex);
    }
    
  2. N'oubliez pas d'utiliser le même objet d'expression régulière avec les appels suivants. Parce que, l'objet regex est mis à jour à chaque fois, et si vous passez un nouvel objet, encore une fois le programme se déroulera dans une boucle infinie.

    var myString = "[22].[44].[33].", result;
    
    while (result = /\d+/g.exec(myString)) {
        console.log(result);
    }
    
46
répondu thefourtheye 2015-08-12 18:05:10

String.prototype.match() et RegExp.prototype.exec() sont similaires à la fois pour trouver plusieurs occurrences et les renvoyer dans un tableau. Pourtant, la méthode exec renvoie un tableau d'informations plus détaillées. Par exemple, contrairement à match, il peut également trouver plusieurs occurrences des groupes de capture. Donc si vous avez des groupes de capture, exec est essentiel. Une chose à garder à l'esprit lorsque vous travaillez avec exec, vous ne devriez pas invoquer if À partir d'une expression rationnelle littérale. Affectez d'abord votre expression rationnelle à une variable et utilisez-la pour appeler votre méthode exec. Une autre chose est, alors que match apporterait plusieurs occurrences dans un tableau d'éléments en une seule fois, avec exec, vous devez itérer pour chaque occurrence à capturer.

Invoquer match est assez simple. Comme il s'agit d'une méthode prototype de chaîne, vous l'enchaînez simplement à une chaîne et fournissez une expression rationnelle comme argument à la méthode de correspondance comme; "test".match(/es/) Une représentation littérale d'une expression régulière peut être utilisé sans problème.

Invoquer exec est plus compliqué. Comme je l'ai mentionné précédemment il est préférable d'avoir le regex assigné à quelque chose précédemment. Ok permet de voir un exemple

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");

Comme vous le voyez, le résultat d'exec inclut également les groupes de capture. La façon dont je choisis de remplir le tableau te est quelque peu peu orthodoxe mais je déteste utiliser un tableau temporaire juste dans la partie conditionnelle de la boucle while. Cela me semble beaucoup plus soigné. La seule chose est, le null final pour arrêter la boucle while est inséré à la fin du tableau te. D'où l'instruction te.length-- suivante.

1
répondu Redu 2016-05-12 13:34:01