Parser du BBCode en PHP avec une RegEx

Résolu/Fermé
Captain_Cook Messages postés 23 Date d'inscription lundi 28 juillet 2008 Statut Membre Dernière intervention 27 août 2008 - 27 août 2008 à 21:37
Captain_Cook Messages postés 23 Date d'inscription lundi 28 juillet 2008 Statut Membre Dernière intervention 27 août 2008 - 27 août 2008 à 21:52
Bonjour,

j'ai un petit (mais très embêtant...) problème avec une expression rationnelle : mon but est d'afficher le code source contenu dans mes articles dans des paires de balises [code][\/code] (je mets un anti-slash pour le forum). Dans ma base de données (MySQL), les chevrons sont déjà remplacés par < et > (LE CODE XHTML DES CHEVRONS EST INTERPRETE PAR LE FORUM -_-) (j'ai une fonction qui me les remplace lorsque j'envoie l'article depuis mon espace admin).

Voici le chemin pour qu'un article apparaisse sur mon site :

1. Je tape l'article dans mon espace admin (créé par mes soins :p). À ce moment, les chevrons sont sous leur forme initiale : < et >, j'ai donc dans le textarea de mon article des balises du type [code]<?php echo 'Hello World!'; ?>[\/code].

2. Je valide le formulaire : là, j'utilise deux str_replace successifs pour transformer les chevrons en leurs entités xhtml, puis je les stocke dans ma base de données. La balise précédente est donc stockée dans ma base de données sous la forme [code]<?php echo 'Hello World!'; ?>[\/code].

==> 3. Lorsque l'article en question est appelé à l'écran, j'ai une autre fonction qui parse le contenu de l'article à la recherche des paires de balises [code][\/code] pour afficher le code d'une manière plus conviviale. Le problème, c'est que le contenu des paires de balises [code][\/code] peut s'étaler sur plusieurs lignes...

J'ai alors tenté de parser mon article avec la regex suivante : '#\[code\](.*)\[\/code\]#', en écrivant ceci :

// Note 1 : $output contient tout mon article
// Note 2 : display_script() est une fonction qui affiche le code plus joliment :p

$code = '#\[code\](.*)\[\/code\]#';
if (preg_match( $code, $output)) { $output = preg_replace( $code, display_script( '\\1'), $output);}

Mais avec celle-ci, je ne récupère que les codes qui ne contiennent qu'une seule ligne car . n'inclut pas \n...

J'ai essayé ensuite avec '#\[code\]((.|\n)*)\[\/code\]#', écrivant ceci :

$code = '#\[code\]((.|\n)*)\[\/code\]#';
if (preg_match( $code, $output)) { $output = preg_replace( $code, display_script( '\\1'), $output);}

Là, c'est n'importe quoi : le navigateur me propose de télécharger la page qui exécute ce code... mais est-ce comme cela ('\\1') que l'on accède à ce qui a été trouvé lorsqu'il y a deux paires de parenthèse imbriquées ??

Enfin, j'ai tenté la regex : '#\[code\](.*)\[\/code\]#s', en écrivant ceci :

$code = '#\[code\](.*)\[\/code\]#s';
if (preg_match( $code, $output)) { $output = preg_replace( $code, display_script( '\\1'), $output);}

Mais là encore, problème : la fonction me renvoie une seule chaine de type '<truc1>[\/code][code]<truc2>[\/code][code]<truc3>' car le parsing s'arrête au dernier [\/code], pareil pour la regex '#\[code\](.*)\[\/code\]#sm'...

Je ne sais plus quoi faire, est-ce quelqu'un saurait comment parser un tel fichier pour que TOUTES les paires de balises [code][\/code] soient parsées, mais que le parsing s'arrete à la première balise de fin [\/code] rencontrée ??

Merci beaucoup.
A voir également:

2 réponses

Rctll Messages postés 499 Date d'inscription dimanche 11 mai 2008 Statut Membre Dernière intervention 30 juin 2010 1 409
27 août 2008 à 21:44
Bonsoir
As tu essayé le modificateur U (Ungreedy)
ca donnerai qqchose comme :
$code = '#\[code\](.*)\[\/code\]#sU';
if (preg_match( $code, $output)) { $output = preg_replace( $code, display_script( '\\1'), $output);}
4
Captain_Cook Messages postés 23 Date d'inscription lundi 28 juillet 2008 Statut Membre Dernière intervention 27 août 2008 2
27 août 2008 à 21:52
Bonsoir,

et merci de ta réponse si rapide :D

avec sU, ça Marche !! 1000 mercis :)

Maintenant, il faut que je recode ma fonction d'affichage du code (pour afficher les sauts de ligne correctement)

MERCI ;-)
0