2
votes

Qu'est-ce que le support lookbehind dans JS? Comment le remplacer?

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 >


0 commentaires

3 Réponses :


3
votes

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 is:

const result = input.replace(rex, (m, c) => {
    return c[0] === "i" ? m : "z" + c;
});

Exemple en direct:

const rex = /i(i+|.|$)/g;


0 commentaires

7
votes

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')


0 commentaires

1
votes

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


0 commentaires