Quel est le problème avec cette expression régulière lorsque j'utilise le drapeau global et le drapeau insensible à la casse? La requête est une entrée générée par l'utilisateur. Le résultat devrait être [vrai, vrai].
var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.Push(re.test('Foo Bar'));
result.Push(re.test('Foo Bar'));
// result will be [true, false]
var reg = /^a$/g;
for(i = 0; i++ < 10;)
console.log(reg.test("a"));
L'objet RegExp
garde une trace du lastIndex
où une correspondance s'est produite. Par conséquent, lors des correspondances suivantes, il commencera à partir du dernier index utilisé, au lieu de 0. Regardez:
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'));
Si vous ne souhaitez pas réinitialiser manuellement lastIndex
à 0 après chaque test, supprimez simplement l'indicateur g
.
Voici l'algorithme dicté par les spécifications (section 15.10.6.2):
RegExp.prototype.exec (chaîne)
Effectue une correspondance d'expression régulière de chaîne contre l'expression régulière et retourne un objet Array contenant le résultats de la correspondance, ou null si le chaîne ne correspond pas à la chaîne ToString (string) est recherché pour un occurrence de l'expression régulière motif comme suit:
- Soit S la valeur de ToString (chaîne).
- Soit longueur la longueur de S.
- Soit lastIndex la valeur de la propriété lastIndex.
- Soit i la valeur de ToInteger (lastIndex).
- Si la propriété globale est false, laissez i = 0.
- Si je <0 ou I> longueur, définissez lastIndex sur 0 et renvoie la valeur null.
- Appelez [[Match]] en lui donnant les arguments S et i. Si [[Match]] échec retourné, passez à l’étape 8; sinon, r est le résultat final et passez à l'étape 10.
- Soit i = i + 1.
- Passez à l'étape 6.
- Soit e la valeur endIndex de r.
- Si la propriété globale a la valeur true, définissez lastIndex sur e.
- Soit n la longueur du tableau de capture de r. (Il s'agit de la même valeur Que celle de 15.10.2.1 NCapturingParens.)
- Renvoie un nouveau tableau avec les propriétés suivantes:
- L'index propriété est définie sur la position du correspondance de sous-chaîne dans la totalité chaîne S.
- La propriété d'entrée est définie à S.
- La propriété length est définie sur n + 1.
- La propriété 0 est définie sur le correspondance de sous-chaîne (c'est-à-dire la partie de S entre l'offset i inclus et l'offset e exclusif).
- Pour chaque entier i tel que I> 0 et I ≤ n, définissez la propriété nommée ToString (i) sur le ième élément de r capture le tableau.
Vous utilisez un seul objet RegExp
et l'exécutez plusieurs fois. A chaque exécution successive, il continue à partir du dernier index de correspondance.
Vous devez "réinitialiser" l'expression rationnelle pour qu'elle recommence depuis le début avant chaque exécution:
result.Push(re.test('Foo Bar'));
re.lastIndex = 0;
result.Push(re.test('Foo Bar'));
// result is now [true, true]
Cela dit, il est peut-être plus facile de créer un nouvel objet RegExp à chaque fois (la surcharge est minime, car RegExp est de toute façon mis en cache):
result.Push((/Foo B/gi).test(stringA));
result.Push((/Foo B/gi).test(stringB));
RegExp.prototype.test
met à jour les expressions régulières 'lastIndex
property afin que chaque test commence à l'endroit où le dernier s'est arrêté. Je suggérerais d'utiliserString.prototype.match
puisqu'il ne met pas à jour la propriétélastIndex
:
!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true
Remarque:!!
le convertit en un booléen, puis inverse le booléen afin qu’il reflète le résultat.
Sinon, vous pouvez simplement réinitialiser la propriétélastIndex
:
result.Push(re.test('Foo Bar'));
re.lastIndex = 0;
result.Push(re.test('Foo Bar'));
La suppression de l'indicateur global g
résoudra votre problème.
var re = new RegExp(query, 'gi');
Devrait être
var re = new RegExp(query, 'i');
J'ai eu la fonction:
function parseDevName(name) {
var re = /^([^-]+)-([^-]+)-([^-]+)$/g;
var match = re.exec(name);
return match.slice(1,4);
}
var rv = parseDevName("BR-H-01");
rv = parseDevName("BR-H-01");
Le premier appel fonctionne ... Le second appel ne fonctionne pas. L'opération slice
se plaint d'une valeur nulle. Je suppose que cela est dû au re.lastIndex
. C'est étrange car je m'attendrais à ce qu'une nouvelle RegExp
soit allouée chaque fois que la fonction est appelée et ne soit pas partagée entre plusieurs appels de ma fonction.
Quand je l'ai changé pour:
var re = new RegExp('^([^-]+)-([^-]+)-([^-]+)$', 'g');
Ensuite, je ne reçois pas l’effet de retenue lastIndex
. Cela fonctionne comme je l’attendais.
Utiliser le drapeau/g lui dit de continuer à chercher après un hit.
Avant votre première recherche:
myRegex.lastIndex
//is 0
Après la première recherche
myRegex.lastIndex
//is 8
Supprimez le g et il quitte la recherche après chaque appel à exec ().