312 votes

Pourquoi RegExp avec indicateur global en Javascript donnent des résultats erronés ?

Quel est le problème avec cette expression régulière lorsque j’utilise l’indicateur global et le drapeau de la casse ? La requête est une entrée généré par l’utilisateur. Le résultat devrait être [true, vrai].

390voto

Ionuț G. Stan Points 62482

L' RegExp objet garde une trace de l' lastIndex où une correspondance s'est produite, de sorte que sur les matchs suivant, il va commencer à partir du dernier indice utilisé, au lieu de 0. Prendre un coup d'oeil:

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));

alert(re.lastIndex);

result.push(re.test('Foo Bar'));

Autant que je sache, seul Firefox 3+, vous permet de spécifier l' sticky drapeau (y), ce qui permet de réinitialiser le compteur après chaque match. Sinon, vous pouvez réinitialiser manuellement.

Voici l'algorithme que les spécifications dicter (section 15.10.6.2):

RegExp.le prototype.exec(string)

Effectue une expression régulière de la chaîne à l'encontre de l'expression régulière et retourne un Tableau d'objets contenant de l' résultats du match, ou null si l' la chaîne ne correspond pas à La chaîne ToString(string) est recherché pour un occurrence de l'expression régulière modèle comme suit:

  1. Soit S la valeur de ToString(string).
  2. Permettez-être la longueur de la longueur de S.
  3. Laissez lastIndex être la valeur de la propriété lastIndex.
  4. Laissez-je être la valeur de ToInteger(lastIndex).
  5. Si la propriété est fausse, soit i = 0.
  6. Si I < 0 ou I > longueur puis définissez lastIndex de 0 et de retourner la valeur null.
  7. Appel [[Match]], en lui donnant les arguments S et je. Si [[Match]] renvoyé un échec, passez à l'étape 8; sinon, soit r son État de résultat et passez à l'étape 10.
  8. Soit i = i+1.
  9. Passez à l'étape 6.
  10. Soit e r endIndex valeur.
  11. Si la propriété est vraie, ensemble lastIndex à l'e.
  12. Soit n la longueur de la r de la capture de tableau. (C'est la même chose valeur 15.10.2.1 de l' NCapturingParens.)
  13. De retour d'un nouveau tableau avec les propriétés suivantes:
    • L'indice la propriété est à la position de la sous-chaîne correspondante dans l'ensemble de l' chaîne S.
    • L'entrée de la propriété est définie S.
    • La longueur de la propriété est définie à n + 1.
    • La 0 la propriété est définie à l' sous-chaîne correspondante (c'est à dire la partie de S décalage entre je inclusive et décalage e exclusive).
    • Pour chaque entier i tel que I > 0 et I ≤ n, définissez la propriété nommée ToString(i) à le i-ème élément de la r de la capture de tableau.

78voto

Roatin Marth Points 9532

Vous utilisez un seul `` objet et l’exécuter plusieurs fois. Sur chaque exécution successive, il continue sur partir du dernier index de correspondance.

Vous avez besoin de l’expression régulière à commencer dès le début avant chaque exécution de « reset » :

Cela dit qu’il serait plus lisible de créer un nouvel objet RegExp chaque fois (frais généraux est minime, car l’expression rationnelle est mise en cache de toute façon) :

38voto

James Points 56229

RegExp.prototype.test mises à jour régulières les expressions' lastIndex de la propriété, de sorte que chaque test démarre lorsque le dernier arrêté. Je suggérerais à l'aide de String.prototype.match puisqu'il n'a pas de mise à jour de l' lastIndex de la propriété:

!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true

Remarque: !! convertit une valeur de type boolean et puis inverse le booléen de sorte qu'il reflète le résultat.

Alternativement, vous pouvez simplement réinitialiser l' lastIndex de la propriété:

result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));

13voto

user2572074 Points 21

Indicateur global (g) supprimer va résoudre votre problème.

var re = new RegExp (requête, 'gi') ; var doit être re = new RegExp (requête, 'i') ;

-1voto

Anatoliy Points 7775

C’est parce que les premiers test-matches avec « Foo B » et deuxième test sans correspondance avec « ar ».

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