2010-06-17 9 views
2

J'écris BBcode convertisseur en HTML.
Le convertisseur doit ignorer les étiquettes non fermées.Regex BBCode au format HTML

Je pensais à 2 options pour le faire:
1) correspondent à tous les tags en une fois en utilisant un appel regex, comme:

Regex re2 = new Regex(@"\[(\ /?(?:b|i|u|quote|strike))\]"); 
MatchCollection mc = re2.Matches(sourcestring); 

puis, boucle sur MatchCollection en utilisant 2 pointeurs pour trouver démarrer et ouvert tags et que le remplacement avec la balise html droite.

2) appellent regex temps multiples pour chaque étiquette et remplacer directement:

Regex re = new Regex(@"\[b\](.*?)\[\/b\]"); 
string s1 = re.Replace(sourcestring2,"<b>$1</b>"); 

Qui plus est efficace?

La première option utilise une regex, mais elle nécessite que je parcourt toutes les balises et trouve toutes les paires, et ignore les balises qui n'en ont pas.
Un autre point positif est que je ne me soucie pas du contenu entre les tags, je travaille juste et les remplace en utilisant la position. Dans la deuxième option, je n'ai pas besoin de m'inquiéter de faire une boucle et de faire une fonction de remplacement spéciale.
Mais il faudra exécuter plusieurs regex et les remplacer.

Que pouvez-vous suggérer?

Si la deuxième option est la bonne, il y a un problème avec regex \[b\](.*?)\[\/b\]

comment puis-je résoudre ce problème pour correspondre aussi multi lignes comme:

[b] 
     test 1 
[/b] 

[b] 
     test 2 
[/b] 

Répondre

1
r = new System.Text.RegularExpressions.Regex(@"(?:\[b\])(?<name>(?>\[b\](?<DEPTH>)|\[/b\](?<-DEPTH>)|.)+)(?(DEPTH)(?!))(?:\[/b\])", System.Text.RegularExpressions.RegexOptions.Singleline); 

var s = r.Replace("asdfasdf[b]test[/b]asdfsadf", "<b>$1</b>"); 

Ce ne devrait vous donner que des éléments qui ont correspondu à des balises de fermeture et aussi gérer des lignes multiples (même si j'ai spécifié l'option de SingleLine, il le traite réellement comme une seule ligne)

Il devrait également gérer correctement [b] [b] [/ b] en ignorant le premier [b].

Pour savoir si cette méthode est meilleure que votre première méthode, je ne pourrais pas dire. Mais j'espère que cela vous indiquera la bonne direction.

Code qui fonctionne avec votre exemple ci-dessous: System.Text.RegularExpressions.Regex r;

r = new System.Text.RegularExpressions.Regex(@"(?:\[b\])(?<name>(?>\[b\](?<DEPTH>)|\[/b\](?<-DEPTH>)|.)+)(?(DEPTH)(?!))(?:\[/b\])", System.Text.RegularExpressions.RegexOptions.Singleline); 

var s = r.Replace("[b]bla bla[/b]bla bla[b] " + "\r\n" + "bla bla [/b]", "<b>$1</b>"); 
+0

il ne fonctionne pas sur une chaîne comme: "[b] bla bla [/ b] bla bla [b]" + "\ r \ n" + "bla bla [/ b]"; – ilann

+0

Testé avec ce code exact et cela a fonctionné très bien, donc je ne suis pas tout à fait sûr de ce que le problème pourrait être. Mais si vous pouviez copier le code ci-dessus et vérifier cela :) Éditer: déplacer le code dans ma réponse – Buildstarted

2

Une option serait d'utiliser plus parsing comme SAX, où au lieu de chercher une expression rationnelle particulière que vous recherchez [, alors votre programme gérer que même d'une certaine manière, recherchez le ], gérer que même, etc. Bien que plus verbeux que l'expression rationnelle, il peut être plus facile à comprendre et ne sera pas nécessairement plus lent.