Page 1 sur 2
regex
Posté : 22 mai 2006, 12:19
par jojolapine
bonjour à tous, dnas le but de mettre en forme un texte avec des balises du style bbcode, j'ai fait cette fonction:
function mise_en_forme($texte){
$texte=str_replace("[gras]","<b>",$texte);
$texte=str_replace("[/gras]","</b>",$texte);
$texte=str_replace("[italique]","<i>",$texte);
$texte=str_replace("[/italique]","</i>",$texte);
$texte=str_replace("[souligne]","<span style=\"text-decoration: underline;\">",$texte);
$texte=str_replace("[/souligne]","</span>",$texte);
$texte=str_replace("[ quote]","<div class=\"quote\">",$texte);
$texte=str_replace("[/quote]","</div>",$texte);
return $texte;
}
je voudrait savoir comment l'arranger en faisant qqch du style:
recherche dans $texte [gras]n'importequoiaumilieu[/gras] et remplace le par <b>lemêmen'importequoi</b>
mais je sais pas du tout comment m'y prendre...
merci d'avance[/php]
Posté : 22 mai 2006, 16:07
par Ryle
Tu peux utiliser la fonction ereg_replace pour rechercher une expression régulière et la remplacer.
Tu aurais quelque chose du genre
$str = ereg_replace(
"#\[gras\](.*)\[/gras\]#",
"<b>$1</b>",
$str);
le $1 correspondant à ce qui a été capturé par la parenthèse... voir les infos sur les expressions regulières si tu as besoin de plus de détail

Faudra certainement bricoler un peu pour gérer les paires imbriquées ou non équilibrées...
Posté : 22 mai 2006, 16:26
par Ripat
[-X Tss! Tss! La gourmandise est un vilain défaut!
Et les délimiteurs dans une regex posix...
Punition: lire 10x, et en anglais,
Mastering Regular Expressions de
Jeffrey Friedl ainsi que
Programming Perl de
Larry Wall

Posté : 22 mai 2006, 16:35
par béka
je n'ai pas très bien compris ta question, mais si il s'agit de faire de la mise en forme de texte, je peux te proposer cette solution :
une premiere page :
Code : Tout sélectionner
html>
<head>
<title>essai</title>
</head>
<body>
<form method="post" action="inter.php">
<input type=textearea rows=4 name="texte"><br>
Gras : <input type=checkbox name="gras"><br>
Italique : <input type=checkbox name="italique"><br>
Taille : <input name="taille"><br>
<select name="couleur"> Couleur :
<option value="black">Noir</option>
<option value="blue">Bleu</option>
<option value="white">Blanc</option>
<option value="green">Vert</option>
<option value="red">Rouge</option>
</select>
<input value="Envoyer" type="submit">
</form>
</body>
</html>
et une deuxieme page php avec le code suivant :
<?
// Permet de mettre en forme un texte en fonction de plusieurs parametres...
//
//recuperation des parametres
//
$texte=$_POST['texte'];
if(isset($_POST['gras']))
{$gras=$_POST['gras'];}else{$gras="off";};
if(isset($_POST['italique']))
{$italique=$_POST['italique'];}else{$italique="off";};
$taille=$_POST['taille'];
$couleur=$_POST['couleur'];
?>
<html><head><title>essai</title></head>
<body <?
if($couleur!=NULL)
{echo "text=$couleur";};?>>
<?
// suivant les valeurs des variables, on genere les balises HTML qui correspondent, <b> gras, etc...
if($gras=="on")
{echo "<b>";};
if($italique=="on")
{echo "<i>";};
if($taille!="")
{echo "<font size=\"$taille\">";};
/affichage du texte
echo "$texte";
//meme travail qu'au début mais avec fermeture des balises...
// attention ordre inverse de l'ouverture...
if($taille!="")
{echo "</font>";};
if($italique=="on")
{echo "</i>";};
if($gras=="on")
{echo "</b>";};
?>
</body>
</html>
voila, je sais pas si ca t'as aidé
Posté : 23 mai 2006, 12:00
par Ryle
Et les délimiteurs dans une regex posix...
J'ai pas bien compris ? c'était par rapport à l'expression que j'ai donné que tu disais ça ?
J'ai collé des # comme délimiteurs, normalement ca marche pareil que le / sauf que j'ai pas à échapper les slash à l'interieur de ma chaine, nan ?
Posté : 23 mai 2006, 12:24
par Ripat
T'a déjà tout lu 10x?
Non, plus sérieusement, quand tu mets des délimiteurs dans une fonction d'expression rationnelle POSIX comme ereg() ou ereg_replace() ils seront pris comme caractères littéraux.
Les délimiteurs ne sont nécessaires que dans les fonctions PCRE preg_match() et toute sa famille.
Ensuite, tous les quantificateurs comme * dans ton motif sont
gourmands, ils prendront donc tous les caractères jusqu'au dernier [/gras] du texte.
Pour reprendre ton masque, tu pourrais faire:
$str = "Je suis [gras]gras[/gras], gros et [gras]gluant[/gras]";
$str = preg_replace(
"#\[gras\](.*)\[/gras\]#U",
"<b>$1</b>",
$str);
echo $str;
Essaye sans l'option "quantificateur non-gourmand"
U (derrière le délimiteur) et tu verras de suite la conséquence de la gourmandise.

Posté : 23 mai 2006, 12:30
par jojolapine
merci à tous pour vos réponses...
ça marche désormais, mais je n'ai pas bien compris Ripat, sans le U dnas le masque, j'ai quelques balises fermantes ([/..]) qui ne sont pas traduites...
et avec le U tt est comme y faut?
Posté : 23 mai 2006, 12:42
par jojolapine
bon finallement j'en ai pas tout à fait finit, avec la gourmandise...
j'essaye d'adapté la solution donnée plus haut, pour transformé les adresses email en mailto, pour cela j'ai "piqué" le masque proposé dans la faq, voici ce que j'ai:
$masque="#^[^-_\.][a-z0-9-_\.]+[^-_\.]@[^-_\.][a-z0-9-_\.]+[^-_\.]\.[a-z]{2,4}$#U";
$remplace="<a href=\"mailto:$1\">$1</a>";
$texte = preg_replace($masque,$remplace,$texte);
mais je ne sais pas où mettre le *?
Posté : 23 mai 2006, 13:02
par Ripat
Le *, comme le + ou un {2.4} sont tous des quantificateurs.
Dans ton masque, il n'est pas indispensable de rendre les quantificateurs non-gourmands.
Par contre ton masque est un masque de validation d'adresse email. Avec les ancrages ^et $, il ne capturera donc pas une email noyée dans un texte.
Retire-les.
De plus, dans l'argument remplacement, tu appelles la référence arrière $1 qui n'existe pas puisqu'il n'y a pas de parenthèses capturantes. Elle ne sont pas, strictement, nécessaires mais il faut alors changer tes références arrières en $0 - la concordance complète.
Posté : 23 mai 2006, 13:04
par sadeq
Voici une solution qui centralise une base de codes bbcode/html avec une conversion automatique selon le contenu de la base
Cette solution utilise preg_replace pour convertir les codes.
<?php
echo mise_en_forme("[gras]texte en gras[/gras] texte normal [italique]texte en italique[/italique]
texte normal [souligne]texte souligne[/souligne] texte normal [ quote]texte style quote[/quote]");
function mise_en_forme($texte){
//Base de données des tags bbcode/html
$tags = array (
array ("bbcode_d"=>"gras",
"bbcode_f"=>"/gras",
"html_d"=>"b",
"html_f"=>"/b"),
array ("bbcode_d"=>"italique",
"bbcode_f"=>"/italique" ,
"html_d"=>"i",
"html_f"=>"/i"),
array ("bbcode_d"=>"souligne",
"bbcode_f"=>"/souligne",
"html_d"=>"span style='text-decoration: underline;'",
"html_f"=>"/span"),
array ("bbcode_d"=>" quote",
"bbcode_f"=>"/quote",
"html_d"=>"div class='quote'",
"html_f"=>"/div")
);
//Conversion bbcode/html
foreach ($tags as $tag) {
$bbcode_d = $tag["bbcode_d"];
$bbcode_f = $tag["bbcode_f"];
$html_d = $tag["html_d"];
$html_f = $tag["html_f"];
$texte = preg_replace("#\[$bbcode_d\](.*)\[$bbcode_f\]#","<$html_d>$1<$html_f>",$texte);
}
return $texte;
}
?>
<style>
.quote {padding-left:20; background:silver; color:blue; border-style:solid; border-width:1px; font-style:italic; font-size:14}
</style>
Posté : 23 mai 2006, 13:10
par jojolapine
Par contre ton masque est un masque de validation d'adresse email. Avec les ancrages ^et $, il ne capturera donc pas une email noyée dans un texte.
justement, comment faire pour que ce masque capture l'adresse email, en faisant ça ça marchepas:
$remplace="<a href=\"mailto:$1\">$1</a>";
$masque="#[-_\.][a-z0-9-_\.]+[-_\.]@[-_\.][a-z0-9-_\.]+[-_\.]\.[a-z]{2,4}#";
$texte = preg_replace($masque,$remplace,$texte);
Posté : 23 mai 2006, 13:24
par Ripat
Un truc du genre:
$texte = preg_replace("#[^-_\.][a-z0-9-_\.]+[^-_\.]@[^-_\.][a-z0-9-_\.]+[^-_\.]\.[a-z]{2,4}#","<a href=\"mailto:$0\">$0</a>", $texte);
Sadeq --> La fonction est élégante mais, même remarque, ton quantificateur est gourmand. Et, de plus, ton dot dans
(.*) ne prendra pas les retours lignes.
Si tu as un texte comme:
Ton motif s'arrêtera au retour ligne.
Je corrigerais ton masque comme ceci:
$texte = preg_replace("#\[$bbcode_d\](.*)\[$bbcode_f\]#Us","<$html_d>$1<$html_f>",$texte);
Avec les options
Uet
s
Posté : 23 mai 2006, 13:32
par jojolapine
merci pour la réponse, Ripat, y a un petit quelquechose qui va pas, j'ai un espace capturé au début de chaque adresse e-mail, et vu que pige pas grand chose...
et au fait, pourquoi on récupère avec $0 la capture alors que plus haut on récupère avec $1
sinon je quémande une denière fois, tjrs depuis la faq, j'ai récupéré ce masque:
Code : Tout sélectionner
#^(?:(?:https?|ftp)://)?(?:w{3}\.)?[^\W]?[\w-\.]*[^\W]?\.[a-z]{2,4}
(?:/(?:~?[^\W]?[\w-\./]*[^\W]?(?:\.[a-z]{2,4})?(?:\?\w+=\w+(?:(?:&|&)\w+=\w+)*)?)?)?$#i
et comme tu t'en doute, je n'arriva pas à le faire marcher dans un preg_replace avec capture
merci d'avaance
Posté : 23 mai 2006, 13:41
par Ripat
Pour l'espace, remplace la première classe de caractères [^-_\.] par l'assertion simple \b (séparateur de mots)
preg_replace("#[^-_\.]... ---> preg_replace("#\b...
Pour tes autres question, il serait utile que tu passes un peu de temps sur un tuto de base sur les regex. C'est dur à avaler au début mais c'est un bon investissement. Les regex sont utilisées dans quasiment tous les langages informatiques.
La paternité des expressions relationnelles modernes revient à Larry Wall, linguiste de fprmation et concepteur de Perl.
Posté : 23 mai 2006, 13:44
par jojolapine
merci pour l'espace ça fonctionne !
par contre je galère pour les adresses web

je vous jure que c'est la dernière chose que je demande, après je prendrait un tutos sur les expressions régulières, mais en cemoment, j'ai pas le temps, c'est les partiels et je doit en même temps présenter ce projet, alors bon ...
merci d'avance