J'ai une chaîne et je veux remplacer chaque «i» qui n'est PAS suivi / suivi par un autre i et le remplacer par «z». Je sais qu'il y a une anticipation et un regard négatifs.
Les résultats doivent être:
/i(?!i)/gi
J'ai essayé d'utiliser ceci:
/(?<!i)i(?!i)/gi
et il a échoué et a généré une erreur: Groupe de regex non valide
.
Pourtant
i => z iki => zkz iiki => iikz ii => ii iii => iii
fonctionne bien, mais correspond deuxième "i" dans ceci: "ii".
Y a-t-il un autre moyen?
Quel est le support de lookbehind dans JS s'il y en a?
p >
3 Réponses :
Regarder en arrière dans les expressions régulières JavaScript est assez récent. Au moment de la rédaction de cet article, il est pris en charge uniquement dans V8 (dans Chrome , Chromium, Brave ...), pas par d'autres moteurs.
Il y a beaucoup de questions avec des réponses ici sur la façon de contourner le fait de ne pas avoir regardé en arrière, comme celle-ci a>.
Cet article de Steven Levithan également montre des moyens de contourner l'absence de fonctionnalité.
Je veux remplacer chaque «i» qui n'est PAS suivi / suivi par un autre i et le remplacer par «z»
C'est assez facile à faire sans regarder ni regarder en arrière, en utilisant des espaces réservés et un groupe de capture. Vous pouvez capturer ce qui suit le i
:
const rex = /i(i+|.|$)/g; function test(input, expect) { const result = input.replace(rex, (m, c) => { return c[0] === "i" ? m : "z" + c; }); console.log(input, result, result === expect ? "Good" : "ERROR"); } test("i", "z"); test("iki", "zkz"); test("iiki", "iikz"); test("ii", "ii"); test("iii", "iii");
... puis le remplacer conditionnellement si ce qui a été capturé n'est pas un i
ou une série de i
s:
const result = input.replace(rex, (m, c) => { return c[0] === "i" ? m : "z" + c; });
Exemple en direct:
const rex = /i(i+|.|$)/g;
Dans votre cas, vous n'avez pas vraiment besoin de regarder en arrière:
function test(input, expect) { const result = input.replace(/i+/g, (m0) => m0.length > 1 ? m0 : 'z'); console.log(input + " => " + result + " // " + (result === expect ? "Good" : "ERROR")); } test('i', 'z'); test('iki', 'zkz'); test('iiki', 'iikz'); test('ii', 'ii'); test('iii', 'iii');
Vous pouvez simplement utiliser une fonction comme pièce de rechange et tester la longueur de la chaîne correspondante.
Voici tous vos cas de test:
'iiki'.replace(/i+/g, (m0) => m0.length > 1 ? m0 : 'z')
Un hack que vous pouvez utiliser dans ce cas. modifie la valeur de décalage en fonction de la correspondance.
let arr = ['i','iki','iiki','ii','iii', 'ki'] arr.forEach(e=>{ let value = e.replace(/i(?!i)/g, function(match,offset,string){ return offset > 0 && string[offset-1] === 'i' ? 'i' : 'z' }) console.log(value) })