2009-09-07 7 views
1

J'espère que cela aura une réponse assez rapide et simple. J'utilise regular-expressions.info pour m'aider à obtenir la bonne expression régulière pour transformer un signe d'index ISO-8859-1, codé en URL («% A3»), en un signe d'index UTF-8 codé en URL («% C2% A3») . En d'autres termes, je veux juste échanger% A3 avec% C2% A3, alors que% A3 n'est pas déjà préfixé avec% C2.Javascript Expressions régulières Lookbehind défaut

J'aurais pensé ce qui suit fonctionnerait:

Regular Expression: (?!(\%C2))\%A3 
Replace With:  %C2%A3 

Mais il ne fonctionne pas et je ne peux pas comprendre pourquoi!

Je suppose que ma syntaxe est légèrement fausse, mais je ne peux pas le comprendre! Des idées?

FYI - Je sais que ce qui suit fonctionnera (et l'a utilisé comme une solution de contournement dans l'intervalle), mais je veux vraiment comprendre pourquoi le premier ne fonctionne pas.

Regular Expression: ([^\%C2])\%A3 
Replace With:  $1%C2%A3 

TIA!

+0

Je pense que vous avez plutôt besoin d'un convertisseur de codage pour convertir l'ISO 8859-1 en UTF-8. – Gumbo

Répondre

4

Pourquoi ne pas simplement remplacer ((%C2)?%A3) par %C2%A3, faisant du préfixe une partie optionnelle de la correspondance? Cela signifie que vous «remplacez» le texte par rapport à lui-même, même si c'est déjà le cas, mais je ne prévois pas de problème de performance.

+0

Sonne bien - je ne sais pas pourquoi je n'ai pas pensé à ça - merci! :) Ne pas l'accepter comme la réponse car c'est essentiellement une autre solution de contournement (le but de la question était de savoir pourquoi mon lookbehind ne fonctionnait pas), mais merci! – FrostbiteXIII

+0

Ignorer cela - réponse acceptée - merci beaucoup! :) – FrostbiteXIII

+0

Très bien, +1. Vous pouvez utiliser '(?: (?:% C2)?% A3)' car les références arrières ne sont pas vraiment nécessaires dans ce cas. – Tomalak

4

Malheureusement, la syntaxe (?!) Est négative. Au meilleur de ma connaissance, JavaScript ne supporte pas lookbehind négatif. Ce que vous pouvez faire est quand même d'avancer avec le remplacement, et finir avec des chaînes% C2% C2% A3, mais celles-ci pourraient facilement être converties en un second passage au% C2% A3 désiré.

+0

J'ai demandé deux ou trois fois si les opérateurs lookbehind seraient ajoutés à ECMAScript, sur le newsgroup mozilla.dev.tech.js-engine et ne recevraient pas de réponse. N'hésitez pas à ajouter votre voix. http://groups.google.com/group/mozilla.dev.tech.js-engine/browse_thread/thread/5d8e24ca46aa72f1?hl=fr# –

+0

Merci pour la réponse rapide. Ça a l'air stupide, mais je trouve très difficile de comprendre la différence majeure entre lookahead et lookbehind - à mon avis (et je sais que je me trompe, sinon il n'y aurait pas deux noms différents pour ça!), Ça fait juste un rechercher des caractères, mais ne pas les utiliser pour le remplacement? Et merci pour la suggestion, mais je pense que ma solution de contournement est légèrement plus propre. :) – FrostbiteXIII

+0

Pensez-y de cette façon ... les expressions régulières fonctionnent souvent en gardant une trace de l'endroit où vous vous trouvez actuellement dans la chaîne. Cela peut être au détriment de déterminer où vous avez été (lookbehind) et où vous allez (lookahead). Il y a peut-être des difficultés de mise en œuvre avec la mise en œuvre de lookbehind en raison du coût du suivi de votre position actuelle. –

3

Vous pouvez remplacer

(^.?.?|(?!%C2)...)%A3 

avec

$1%C2%A3 
+0

Cela semble trop correspondre dans certains cas. Essayez de faire correspondre cela avec le texte "ladskfjdkfj% A3" et il apparaît que kfj% A3 est apparié. –

+0

... jusqu'à ce que je supprime les ellipses, mais même alors, la chaîne "ladskfjd% C2% A3" correspond bien à ce qu'elle ne devrait pas ... JavaScript ne rend pas cela facile! –

+0

@Tomalak: +1 C'est ce que j'aurais écrit. – Gumbo

1

Je vous suggère d'utiliser the functional form of Javascript String.replace (voir la section "Définition d'une fonction en tant que paramètre"). Cela vous permet de mettre une logique arbitraire, y compris l'état si nécessaire, dans une session de regexp-matching. Pour votre cas, j'utiliserais une expression rationnelle plus simple qui correspond à un surensemble de ce que vous voulez, puis dans l'appel de fonction, vous pourrez tester si elle répond à vos critères exacts, et si ce n'est pas le cas, retourner la chaîne correspondante. Le seul problème avec cette approche est que si vous avez des correspondances potentielles qui se chevauchent, vous avez la possibilité de manquer la seconde correspondance, car il n'y a aucun moyen de retourner une valeur pour indiquer à la méthode replace() qu'elle n'est pas vraiment un match après tout.

Questions connexes