[PHP] - Aide : Expression Régulière

- Aide : Expression Régulière [PHP] - PHP - Programmation

Marsh Posté le 03-02-2006 à 10:51:05    

Bonjour tout le monde !
 
Voilà, j'expose mon problème actuel.
 
J'écrit une expression régulière qui doit formatter en (x)HTML les tags du jeu TrackMania Nation.
 
En effet, j'ai un serveur dédié, et je récupère en php, la liste des joueurs sur ce serveur.
 
Les pseudos peuvent être formatter avec des "balises" particulière pour afficher de la couleur ou faire de la mise en forme.
 
Je me suis donc lancé dans l'ecriture de cette Regex.
 
Voilà ce qu'il faut formatter :
 
- Couleur :
$f80[MLTI]-Blap > [MLTI]-Blap
$f0fTEST$00fTEST2 > TESTTEST2
$f80[MLTI]-Bl$zap > [MLTI]-Blap
( meme chose avec n couleur )
 
Explication : les couleur sont definies via un code $FFF. Il n'y a pas de balise de fermeture. La couleur reste appliqué jusqu'à ce qu'un autre la remplace ou qu'un caractère $z ( fermeture de tout les tag ) soit affiché.
 
- Les autres tag ( toujours sans tag de fermture, mis à part le $z valable pour tout le monde )
 
$i: italic
$s: shadowed <- à oublier
$w: wide spacing
$n: narrow spacing
$m: normal setting <- à oublier pour le moment
$g: default color <- à oublier pour le moment
$z: reset all
 
Pour ces tag là, pas de pb, c'est assez simple.
 
Ou j'en suis :
 
Je me suis attacher à utiliser preg_replace(). ( j'utilise des array() pour appliquer successivement les paterns )
 
Voilà donc mon code, pour l'italique par exemple :
 

Code :
  1. //$str est la chaine à annalyser
  2. $pattern = array('/\\$i(.*)\\$z|\\$i(.*)/');
  3. $replacement = array('<span style="font-style: italic">$1</span>');
  4. preg_replace($pattern, $replacement, $str);


 
Ce code fonctionne bien, et c'est le même pour $w et $n ( à part la mise en forme )
 
La où j'ai un problème c'est avec les couleurs.
 
En effet, le code couleur HTML et sur 6 caractères, celui du Trackmania sur 3. En doublant chacun des caractères, on obtient le bon code HTML. De plus, le $z ( annulant la mise en forme ) est assez embettant.
 
Ce que j'ai pour le moment qui fonctionne "presque" bien :

Code :
  1. $pattern = array('/\\$[w|i|n|m|g|z|s]/','/\\$+([0-9a-f])+([0-9a-f])+([0-9a-f])(.*)\\$+([0-9a-f])+([0-9a-f])+([0-9a-f])(.*)/i','/\\$+([0-9a-f])+([0-9a-f])+([0-9a-f])(.*)/');
  2. $replacement = array('','<font color="#$1$1$2$2$3$3">$4</font><font color="#$5$5$6$6$7$7">$8</font>','<font color="#$1$1$2$2$3$3">$4</font>');


 
( ce code fonctionne pour une ou 2 couleurs, et ne tient pas compte des autres balises de mise en forme
$f80[MLTI]-Blap > [MLTI]-Blap OK
$f0fTEST$00fTEST2 > TESTTEST2 OK
$f80[MLTI]-Bl$zap > [MLTI]-Blap NO
$f0fTEST$00fTEST2$f0fTEST3 > TESTTEST2TEST3 edit: En fait, ca marche bien avec 3 couleurs ...
 
 )
 
Pour mes tests, le 1er patern annule toutes les balises inutiles.

Maintenant, si j'essaye mon code avec 3 couleurs, ca ne vas pas. Je n'arrive pas à generaliser.
Ca fonctionne avec 3 couleurs, par contre, j'arive pas à ajouter le $z
Deplus quand j'introduit la notion de $z dans mon code, ca devient encore plus lourd ! ( en plus de ne pas fonctionner )
 
Alors voilà ... si vous pouvez m'aider à ecrire cette Regex !
 
Je suis dispo pour toutes questions !
 
Merci de m'avoir lu jusqu'ici !
 
@+
 
edit: mes tests sont accessible sur cette page ( affiche la source, les <span> empechant de comprendre correctement )


Message édité par bl@p_psx le 03-02-2006 à 11:00:43

---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 10:51:05   

Reply

Marsh Posté le 03-02-2006 à 11:01:54    

Les expressions régulières ça me casse le crâne, je vais pas être motivé là :p
 
Par contre, pour ton problème de $z, peut-être peux-tu :
1) ne placer que des balises ouvrantes avec tes regex.
2) les fermer dans un second temps sans utiliser de regex : si tu tombes sur une balise, tu fermes la précédente ; idem si tu tombes sur un $z. A mon avis ça peut-être fait sans regex avec des explodes bien placés, basés sur le ">" et le "<".  
 
J'ai pas trop étudier ton problème, mais ça peut être éventuellement moins casse tête en procédant ainsi. Mais je le répète, c'est une idée comme ça, pas cogitée ^^


Message édité par Djebel1 le 03-02-2006 à 11:02:14
Reply

Marsh Posté le 03-02-2006 à 11:07:57    

c'est une idée oui, mais sans regex, j'ai dejà essayé, et c'est encore pire !!!  
 
J'ai tester caractère par caractère et à base d'explode ... c'est beaucoup moins concluant, et bcp plus complexe à ecrire meme de rien !
 
Pour ta solutions, c'est pas si simple que ca ! mais je vais faire quelques test ( en laissant la balise $z dans le code, et en essayant de re-travailler la chaine derière )
 
@+
 
ps: en passant, c'est juste le $z dans la gestion des chaines de couleur  qui me pose problème, pour l'italique ou le wide, c'est pas compliqué !


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 11:32:42    

bah un explode sur les $z, un explode sur <, un explode sur >, on choppe la dernière balise et on la ferme, je pense que ça doit être un tout petit peu moins galère ^^

Reply

Marsh Posté le 03-02-2006 à 11:35:17    

je vais tester ...
 
@+


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 11:38:16    

Salut,
 
juste en passant (ca ne resoud rien, mais bon...) Tu peux écrire les couleurs sur 3 caractères seulement dans les styles, ça peut peut-être simplifier ton expression.

Reply

Marsh Posté le 03-02-2006 à 12:07:22    

En dehors de $z voila comment je ferais:

Code :
  1. $pattern = array(
  2.   '/\$w(.*?)(\$|$)/',
  3.   '/\$i(.*?)(\$|$)/',
  4.   '/\$n(.*?)(\$|$)/',
  5.   '/\$m(.*?)(\$|$)/',
  6.   '/\$g(.*?)(\$|$)/',
  7.   '/\$s(.*?)(\$|$)/',
  8.   '/\$([0-9a-f]{3})(.*?)(\$|$)/',
  9.   '/\$z/'
  10. );
  11. $replace=array(
  12.   '<font style="w">$1</font>$2',
  13.   '<font style="i">$1</font>$2',
  14.   '<font style="n">$1</font>$2',
  15.   '<font style="m">$1</font>$2',
  16.   '<font style="g">$1</font>$2',
  17.   '<font style="s">$1</font>$2',
  18.   '<font style="color:=$1">$2</font>$3',
  19.   '###'
  20. );
  21. while ( strpos($nickname, '$') !== false){
  22.   $nickname = preg_replace($pattern, $replace, $nickname);
  23. }


T'es obligé de faire un while car le $ d'un tag peut être pris par une 1ere pattern ( oui je suis pas clair, mais je fais de mon mieux ;) )
 
Quand au $z c'est plus compliqué, je le ferais ensuite.
Tu dois compter le nombre de balises ouvertes avant celui-ci, remplacer ###(ce par quoi a été remplacé $z dans le code au dessus) par le bon nombre de balises fermantes. Puis supprimer ce nombre de balises fermantes dans le chaine qui suivait ### .... S'pas facile :D
 
edit: quand je dis "je le ferais ensuite" je veux dire: "Je ne pense pas qu'on puisse réussir à le faire en même temps..."

Message cité 1 fois
Message édité par anapajari le 03-02-2006 à 12:11:11
Reply

Marsh Posté le 03-02-2006 à 12:45:05    

stf-m a écrit :

Salut,
 
juste en passant (ca ne resoud rien, mais bon...) Tu peux écrire les couleurs sur 3 caractères seulement dans les styles, ça peut peut-être simplifier ton expression.


 
Bonne nouvelle ! je croyais ( par erreur ) que c'etait #F80 == #F80F80 ... mais non !
 
Apres un cours test : http://download.moultiplayers.net/TMNss.php je m'appercois que tu as raisons ! ca vas simplifier mon bordel !
 
anapajari : je test ca !
 
@+


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 12:53:37    

anapajari a écrit :

En dehors de $z voila comment je ferais:

Code :
  1. $pattern = array(
  2.   '/\$w(.*?)(\$|$)/',
  3.   '/\$i(.*?)(\$|$)/',
  4.   '/\$n(.*?)(\$|$)/',
  5.   '/\$m(.*?)(\$|$)/',
  6.   '/\$g(.*?)(\$|$)/',
  7.   '/\$s(.*?)(\$|$)/',
  8.   '/\$([0-9a-f]{3})(.*?)(\$|$)/',
  9.   '/\$z/'
  10. );
  11. $replace=array(
  12.   '<font style="w">$1</font>$2',
  13.   '<font style="i">$1</font>$2',
  14.   '<font style="n">$1</font>$2',
  15.   '<font style="m">$1</font>$2',
  16.   '<font style="g">$1</font>$2',
  17.   '<font style="s">$1</font>$2',
  18.   '<font style="color:=$1">$2</font>$3',
  19.   '###'
  20. );
  21. while ( strpos($nickname, '$') !== false){
  22.   $nickname = preg_replace($pattern, $replace, $nickname);
  23. }


T'es obligé de faire un while car le $ d'un tag peut être pris par une 1ere pattern ( oui je suis pas clair, mais je fais de mon mieux ;) )
 
Quand au $z c'est plus compliqué, je le ferais ensuite.
Tu dois compter le nombre de balises ouvertes avant celui-ci, remplacer ###(ce par quoi a été remplacé $z dans le code au dessus) par le bon nombre de balises fermantes. Puis supprimer ce nombre de balises fermantes dans le chaine qui suivait ### .... S'pas facile :D
 
edit: quand je dis "je le ferais ensuite" je veux dire: "Je ne pense pas qu'on puisse réussir à le faire en même temps..."


 
Bon, ca fonctionne, de la meme facon que ce que j'ai fait ^^ ( mais en carrement plus simple )
 
J'avais pas penser à faire une boucle ! je debutte carrement en Regex, pas en php, mais en Regex "home made" :D
 
Bon, je vais chercher à compter mes balise post ### ( pour les fermer )
 
@+


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 13:05:29    

grrrr ... faut aussi tenir compte de celle qui sont dejà fermer !!!! Gniiii


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 13:05:29   

Reply

Marsh Posté le 03-02-2006 à 13:19:59    

j'ai trouvé !
 
enfin, je crois, à verifier !
 
pour compter les balises restantes à fermer ( pas de regex )
 

Code :
  1. $tab = explode('###',$nickname);
  2. $chaine_span = "";
  3. for($i=0;$i<(substr_count($tab[0], "<span" ))-(substr_count($tab[0], "</span" ));$i++) {
  4. $chaine_span .= "</span>";
  5. }
  6. //-7 pour enlever le dernier span ...
  7. echo substr($tab[0]."".$chaine_span."".$tab[1],0, strlen($tab[0]."".$chaine_span."".$tab[1])-7);


 
je vais faire des tests dans tous les sens pour verifier que tout fonctione !
 
@+ et encore merci !
 
ps code final :  
 

Code :
  1. function nadeo($nickname) {
  2. $pattern = array(
  3.   '/\$w(.*?)(\$|$)/',
  4.   '/\$i(.*?)(\$|$)/',
  5.   '/\$n(.*?)(\$|$)/',
  6.   '/\$m(.*?)(\$|$)/',
  7.   '/\$g(.*?)(\$|$)/',
  8.   '/\$s(.*?)(\$|$)/',
  9.   '/\$([0-9a-f]{3})(.*?)(\$|$)/',
  10.   '/\$z/'
  11. );
  12. $replace=array(
  13.   '<font style="w">$1</font>$2',
  14.   '<span style="font-style:italic">$1</span>$2',
  15.   '<font style="n">$1</font>$2',
  16.   '<font style="m">$1</font>$2',
  17.   '<font style="g">$1</font>$2',
  18.   '<font style="s">$1</font>$2',
  19.   '<span style="color:#$1">$2</span>$3',
  20.   'REPLACECODELONGEXPRES'
  21. );
  22. //$nickname = '$f00[P$iR] P$f80s$zfyker';
  23. $old = $nickname;
  24. while ( strpos($nickname, '$') !== false){
  25.   $nickname = preg_replace($pattern, $replace, $nickname);
  26. }
  27. //echo $old ." : ".  $nickname."<br />\n";
  28. if(strpos($nickname, 'REPLACECODELONGEXPRES') !== false ) {
  29. $tab = explode('REPLACECODELONGEXPRES',$nickname);
  30. $chaine_span = "";
  31. for($i=0;$i<(substr_count($tab[0], "<span" ))-(substr_count($tab[0], "</span" ));$i++) {
  32.  $chaine_span .= "</span>";
  33. }
  34.  return substr($tab[0]."".$chaine_span."".$tab[1],0, strlen($tab[0]."".$chaine_span."".$tab[1])-7);
  35. }
  36. else return $nickname;
  37. }


Message édité par bl@p_psx le 03-02-2006 à 13:27:12

---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 13:30:26    

marche po :D
 
regarde après transformation ta chaine ressemble à ça:

Code :
  1. <span>A<span>B</span><span>CREPLACECODELONGEXPRES</span></span><span>D</span>


Avec ce que tu fais, tu transformes ta chaine en:

Code :
  1. <span>A<span>B</span><span>C</span></span></span></span><span>D</span>


tu te retrouves donc avec trop de balises span fermantes.
Il faut que tu supprimes de la suite de REPLACECODELONGEXPRES autant de balises fermantes que tu en as rajoutés... Et tout se complique lorsque tu as deux REPLACECODELONGEXPRES  ...

Reply

Marsh Posté le 03-02-2006 à 13:42:37    

Par ailleurs je suis pas sur que ce que je t'ai donné fasse ce qu'il faut :o
 
Si tu as:

Code :
  1. $bAAA$f80BBB$iCCC


tu doit te retrouver avec:

Code :
  1. <span style="font-weight:bold">AAA<span style="color:f80">BBBB<span style="font-style: italic">CCC</span></span></span>


OU

Code :
  1. <span style="font-weight:bold">AAA</span><span style="color:f80">BBBB</span><span style="font-style: italic">CCC</span>


 
Si c'est la 1er solution le code que je t'ai donné marche pas ... mais il suffit de remplacer le (\$|$) par juste $ et ça devrait aller!!!


Message édité par anapajari le 03-02-2006 à 13:42:58
Reply

Marsh Posté le 03-02-2006 à 13:47:56    

exact, je vais regarder sur different test. Il faut savoir que ce pseudo, dans TrackMania est limité en nb de carractère ! la probabilité qu'il y ai 2 $z est tres mince ( mais pas negligeable, je te l'accorde )
 
@+
 
ps: pour l'autre bug, j'avais effectivement vu ca
 
edit, apres test :
 

Code :
  1. $f00$i$w[PR] P$f80s$zfyker


Code :
  1. <span style="color:#f00"><span style="font-style:italic"><span style="font-weight:bold">[PR] P</span></span></span><span style="color:#f80">sREPLACECODELONGEXPRESfyker</span>


Code :
  1. <span style="color:#f00"><span style="font-style:italic"><span style="font-weight:bold">[PR] P</span></span></span><span style="color:#f80">s</span>fyker


 
ca marche bien !
 
Tu matchs toute la chaine à chaque fois, mes spans sont donc avant le $z ...


Message édité par bl@p_psx le 03-02-2006 à 13:55:54

---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 14:06:09    

par contre effectivement, ca ne marche pas avec plus d'un $z ...


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 14:35:51    

bon, petite correction qui modifie correctement le code rendu ( pour un seul $z pour le moment )
 

Code :
  1. return substr($tab[0]."".$chaine_span."".$tab[1],0, strlen($tab[0]."".$chaine_span."".$tab[1])-7*(substr_count($tab[0], "<span" )-substr_count($tab[0], "</span" )))."\n";


 
ainsi que modifier les captures du regex :
 

Code :
  1. $pattern = array(
  2.   '/\$w(.*?)($)/',
  3.   '/\$i(.*?)($)/',
  4.   '/\$n(.*?)($)/',
  5.   '/\$m(.*?)($)/',
  6.   '/\$g(.*?)($)/',
  7.   '/\$s(.*?)($)/',
  8.   '/\$([0-9a-f]{3})(.*?)($)/',
  9.   '/\$z/'
  10. );


 
ce qui donne :

Code :
  1. function nadeo($nickname) {
  2. $pattern = array(
  3.   '/\$w(.*?)($)/',
  4.   '/\$i(.*?)($)/',
  5.   '/\$n(.*?)($)/',
  6.   '/\$m(.*?)($)/',
  7.   '/\$g(.*?)($)/',
  8.   '/\$s(.*?)($)/',
  9.   '/\$([0-9a-f]{3})(.*?)($)/',
  10.   '/\$z/'
  11. );
  12. $replace=array(
  13.   '<span style="font-weight:bold">$1</span>$2',
  14.   '<span style="font-style:italic">$1</span>$2',
  15.   '<span style="n">$1</span>$2',
  16.   '<span style="m">$1</span>$2',
  17.   '<span style="g">$1</span>$2',
  18.   '<span style="s">$1</span>$2',
  19.   '<span style="color:#$1">$2</span>$3',
  20.   'REPLACECODELONGEXPRES'
  21. );
  22. while ( strpos($nickname, '$') !== false){
  23.   $nickname = preg_replace($pattern, $replace, $nickname);
  24. }
  25. if(strpos($nickname, 'REPLACECODELONGEXPRES') !== false ) {
  26. $tab = explode('REPLACECODELONGEXPRES',$nickname);
  27. $chaine_span = "";
  28. $j = 0;
  29. for($i=0;$i<(substr_count($tab[0], "<span" ))-(substr_count($tab[0], "</span" ));$i++) {
  30.  $chaine_span .= "</span>";
  31.  $j++;
  32. }
  33.  return substr($tab[0]."".$chaine_span."".$tab[1],0, strlen($tab[0]."".$chaine_span."".$tab[1])-7*(substr_count($tab[0], "<span" )-substr_count($tab[0], "</span" )))."\n";
  34. }
  35. else return $nickname."\n";
  36. }


 
test :  
 

Code :
  1. echo "<div>\n".nadeo('$f00$i[P$wR] P$f80s$zfyker-grande cha$f80i$ine youpla')."\n</div>\n";
  2. echo "<div>\n".nadeo('$s$f80[MLTI]-Bla$188p')."\n</div>\n";
  3. echo "<div>\n".nadeo('$w$i$ccclOOz|$f00Morph')."\n</div>\n";
  4. echo "<div>\n".nadeo('$f0fTEST$00fTEST2')."\n</div>\n";
  5. echo "<div>\n".nadeo('$f0fTEST$00fTEST2$f0fTEST3')."\n</div>\n";


 
page ici : http://download.moultiplayers.net/TMNss.php
 
et la validation (x)HTML 1.0 strict : http://validator.w3.org/check?uri= [...] &verbose=1
 
modification : j'ai enlever autant de balise span que j'en avais ajouté
 
d'autres remarques ?
 
Merci bcp en tout ca !
 
Je continus de tester !


---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Marsh Posté le 03-02-2006 à 14:56:38    

yes dans tes regex:

Code :
  1. /\$w(.*?)($)/


ça sert a rien d'entourner le $ final de parenthèse tu peux t'en passer. Du coup dans tes replaces les $2 ne sert plus a rien non plus.

Reply

Marsh Posté le 03-02-2006 à 15:18:23    

oki, ca me feras gagner quelques micro secondes ^^
 
Je continus de tester !
 
en prod ici : http://moultiplayers.net/news.php ( en bas de page, à droite ).
 
@+


Message édité par bl@p_psx le 03-02-2006 à 15:19:28

---------------
:Moultiplayers:.:Quatuor Chevalier:.:Admin G15-france.com:.:Wiki -G15-france:.:-Papa-:.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed