2008-09-17 8 views
1

J'essaye d'écrire du JavaScript RegEx pour remplacer les balises entrées par l'utilisateur avec de vraies balises html, donc [b] deviendra <b> et ainsi de suite. le RegEx J'utilise ressemble doncTraitement Javascript Submipps RegEx

var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig; 

avec les éléments suivants JavaScript

s.replace(exptags,"<$1>$2</$1>"); 

cela fonctionne très bien pour les balises imbriquées simples, par exemple:

[b]hello[/b] [u]world[/u] 

mais si les balises sont imbriquées l'un dans l'autre, il ne correspondra qu'aux étiquettes extérieures, par exemple

[b]foo [u]to the[/u] bar[/b] 

cela correspondra uniquement aux balises b. Comment puis-je réparer cela? devrais-je simplement faire une boucle jusqu'à ce que la chaîne de départ soit la même que le résultat? J'ai l'impression que le ((.){1,}?) patten est mal aussi?

Merci

+0

Je ne peux pas croire que personne n'a quitté cette ici: http://stackoverflow.com/a/1732454/20074 – Ken

Répondre

1

AFAIK vous ne pouvez pas exprimer récursion avec des expressions régulières.

Vous pouvez cependant le faire avec System.Text.RegularExpressions de .NET en utilisant une correspondance équilibrée. Voir plus ici: http://blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx

Si vous utilisez .NET, vous pouvez probablement implémenter ce dont vous avez besoin avec un rappel. Sinon, vous devrez peut-être lancer votre propre petit analyseur JavaScript.

Ensuite, si vous pouvez vous permettre d'accéder au serveur, vous pouvez utiliser l'analyseur complet. :)

Pour quoi avez-vous besoin de cela, de toute façon? Si c'est pour autre chose qu'un aperçu, je recommande vivement de faire le traitement côté serveur.

+0

Oui son pour un aperçu en direct pour une zone de commentaires, côté serveur PHP son, mais ont le code pour ce bit. – Re0sless

0

Oui, vous devrez boucler. Alternativement puisque vos étiquettes ressemblent tellement à celles de HTML, vous pouvez remplacer [b] pour <b> et [/b] séparément pour </b>. (.){1,}? est la même chose que (. *?) - c'est-à-dire, tous les symboles, la plus petite longueur de séquence possible.

Mise à jour: Merci à MrP, (.) {1,}? est (.) + ?, mon mauvais.

0

Vous avez raison sur le fait que le motif interne est gênant.

((.){1,}?) 

Cela fait une correspondance capturée au moins une fois, puis le tout est capturé. Chaque personnage à l'intérieur de votre tag sera capturé en tant que groupe.

Vous capturez également le nom de votre élément de fermeture lorsque vous n'en avez pas besoin et utilisez {1} lorsque cela est implicite. Voici une version de nettoyage:

/\[(b|u|i|s|center|code)](.+?)\[\/\1]/ig 

Vous n'êtes pas sûr de l'autre problème.

0

Vous pouvez simplement appliquer l'expression régulière jusqu'à ce qu'elle ne corresponde plus.Cela ferait des choses étranges comme "[b] [b] foo [/ b] [/ b]" => "< b> [b] foo </b> [/ b]" => "< b> < b > foo </b> </b> ", mais autant que je peux voir le résultat final sera toujours une chaîne sensible avec des balises correspondantes (mais pas nécessairement correctement imbriquées).

Ou si vous voulez le faire correctement, écrivez simplement un simple analyseur de descente récursif. Bien que les gens puissent s'attendre à ce que "[b] foo [b] baz [/ u]" fonctionne, ce qui est difficile à reconnaître avec un analyseur.

0

La raison pour laquelle le bloc imbriqué n'est pas remplacé est que la correspondance, pour [b], place la position après [/ b]. Ainsi, tout ce que ((.) {1,}?) Correspond est alors ignoré.

Il est possible d'écrire un analyseur récursif côté serveur - Perl utilise qr// et Ruby a probablement quelque chose de similaire.

Cependant, vous n'avez pas forcément besoin d'une vraie récursivité. Vous pouvez utiliser une boucle relativement simple à manipuler la chaîne équivalente:

var s = '[b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]'; 
var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig; 

while (s.match(exptags)) { 
    s = s.replace(exptags, "<$1>$2</$1>"); 
} 

document.writeln('<div>' + s + '</div>'); // after 

Dans ce cas, il va faire 2 passes:

0: [b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b] 
1: <b>hello</b> <u>world</u> <b>foo [u]to the[/u] bar</b> 
2: <b>hello</b> <u>world</u> <b>foo <u>to the</u> bar</b> 

En outre, quelques suggestions pour le nettoyage de la RegEx:

var exptags = /\[(b|u|i|s|center|code)\](.+?)\[\/(\1)\]/ig; 
  • {1} est supposé lorsqu'aucun autre Il existe
  • compter spécificateurs
  • {1,} peut être réduit à +
+0

Si vous ajoutez [centre] [/ centre] à votre scénario de test, et imbriquez un tag dans un autre, et prenez ma regex d'en bas, je voterai votre réponse. –

+0

Par "imbriquer un tag dans un autre", je voulais dire "la même étiquette à l'intérieur de lui-même", par exemple: [b] foo [b] bar [/ b] baz [/ b] –

0

D'accord avec Richard Szalay, mais son regex ne vous cite droit:

var exptags = /\[(b|u|i|s|center|code)](.*)\[\/\1]/ig; 

est plus propre. Notez que je change également .+? à .*. Il y a deux problèmes avec .+?:

  1. vous ne correspondra pas à [u] [/ u], car il n'y a pas au moins un caractère entre eux (+)
  2. un match non gourmand gagné » t affaire comme bien avec la même étiquette à l'intérieur de lui-même niché
0

que diriez-vous (?):

tagreg=/\[(.?)?(b|u|i|s|center|code)\]/gi; 
"[b][i]helloworld[/i][/b]".replace(tagreg, "<$1$2>"); 
"[b]helloworld[/b]".replace(tagreg, "<$1$2>"); 

Pour moi, le produit ci-dessus:

<b><i>helloworld</i></b> 
<b>helloworld</b> 

Cela semble faire ce que vous voulez, et a l'avantage de ne nécessiter qu'un seul passage.

Disclaimer: Je ne codent pas souvent à JS, donc si je fait des erreurs s'il vous plaît ne hésitez pas à les signaler :-)

3

La solution la plus simple serait de remplacer toutes les balises, si elles sont fermé ou pas et laissez .innerHTML s'entraîner si elles sont appariées ou non, il sera beaucoup plus résilient de cette façon ..

var tagreg = /\[(\/?)(b|u|i|s|center|code)]/ig 
div.innerHTML="[b][i]helloworld[/b]".replace(tagreg, "<$1$2>") //no closing i 
//div.inerHTML=="<b><i>helloworld</i></b>" 
Questions connexes