110 votes

RegExp.exec() renvoie sporadiquement NULL

Je suis sérieusement en train de devenir fou à cause de cela et j'ai déjà passé un temps disproportionné à essayer de comprendre ce qui se passe ici. Alors s'il vous plaît, donnez-moi un coup de main =)

J'ai besoin de faire une correspondance RegExp de chaînes de caractères en JavaScript. Malheureusement, il se comporte de manière très étrange. Ce code :

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

Renvoie "cat" et "dog" pour les deux premiers éléments, comme il se doit, mais ensuite quelques exec() -Les appels commencent à être renvoyés null . Je ne comprends pas pourquoi.

J'ai posté un violon aquí où vous pouvez exécuter et modifier le code.

Jusqu'à présent, j'ai essayé avec Chrome et Firefox.

110voto

SilentGhost Points 79627

Oh, le voilà. Parce que vous définissez votre regex de manière globale, elle correspond d'abord à cat et au deuxième passage de la boucle dog . Il vous suffit donc de réinitialiser votre regex (son pointeur interne). Cf. ceci :

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

89voto

Josué Venegas Points 9

L'objet regex possède une propriété lastIndex qui est mis à jour lorsque vous exécutez exec . Ainsi, lorsque vous exécutez la regex sur, par exemple, "J'ai un chat et un chien aussi", lastIndex est fixé à 12. La prochaine fois que vous exécutez exec sur le même objet regex, il commence à chercher à partir de l'index 12. Vous devez donc réinitialiser le lastIndex entre chaque passage.

40voto

ESL Points 111

Deux choses :

  1. Le besoin mentionné de réinitialiser lors de l'utilisation du g (global). Pour résoudre ce problème, je recommande d'assigner simplement 0 à la lastIndex membre de la RegExp objet. Cette méthode est plus performante que la destruction et la recréation.
  2. Soyez prudent lorsque utiliser in afin de marcher sur un Array car cela peut conduire à des résultats inattendus avec certaines bibliothèques. Parfois, il faut vérifier avec quelque chose comme isNaN(i) ou, si vous savez qu'il n'y a pas de trous, utilisez la boucle for classique.

Le code peut être :

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

5voto

Don Points 41

J'ai eu un problème similaire en utilisant uniquement /g, et la solution proposée ici n'a pas fonctionné pour moi dans FireFox 3.6.8. J'ai réussi à faire fonctionner mon script avec

var myRegex = new RegExp("my string", "g");

J'ajoute ceci au cas où quelqu'un d'autre aurait le même problème que moi avec la solution ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X