pour reprendre la problemeatique :
(copier coller de mon post sur developpez.net)
j'ai créé, pour une action de BTS, un moteur de template.
une de ses fonctionnalitées est de substituer un "bloque" par "autre
chose" (pas important ici)
pour substituer ce block, je doit tout d'abord l'extraire, pour ce
faire, je fait un preg_match() qui me retourne mon block, je fait mes
traitemeznts, puis je fait un str_replace() pour substituer le nouveuax
block.
mon pb se situe au niveau du preg_match :
cette fonction accepte trois parametre.
L'un d'eux est une expression reguliere.
cette expression est : (expliquée juste au dessus) :
"/<li>.*?\[ *testBDD *; *block *= *li *\].*<\/li>/sU"
mon pb :
au lieu de prendre le dernier <li> disponible, elle prend le
premier...cad :
Code:
<li> ne pas me prendre mias quand meme pris </li>
<li> je veut cette partie </li>
<li> ne pas me prendre et ca marche </li>
donnera :
Code:
<li> ne pas me prendre mias quand meme pris </li>
<li> je veut cette partie </li>
alors que je ne veut que :
Code:
<li> je veut cette partie </li>
meric de votre aide svp ))
A voir également:
Une petite aide sur une expression reguliere svp :))
sebmafate
Messages postés4936Date d'inscriptionlundi 17 février 2003StatutMembreDernière intervention14 février 201437 18 oct. 2005 à 15:49
en C# les expressions régulières sont conformes à ECMA. donc je pense que ce sont les mêmes qu'en Perl.
pour en revenir à ton problème :
- as-tu pensé à doubler les \ dans ta chaine, sinon ils sont considérés comme caractères d'échappent.
- tu peux résoudre l'erreur Warning: Unknown modifier '<' in f:\action1 framework\index.php en ajoutant un \ devant les < et les >
donc, pour resummer : j'echappe bien les "<" et les "/", mais j'ai un blocage sur les "<" quand meme...
sinon j'ai bien compris ta regex? (cf le post plus haut)
hansap
Messages postés23Date d'inscriptionvendredi 10 juin 2005StatutMembreDernière intervention19 octobre 2005 18 oct. 2005 à 16:13
alors j'ai essayé a peu pres toutes les alternatives en finissant par :
"(\<\/li>\\s*)<li>.*\<\/li>"
mais ca ne veut pas passer, toujours l'erreure sur le "<"...
ton option /s est elle pour :
<DT>s (<VAR>PCRE_DOTALL</VAR>)
<DD>
Avec cette option, le méta-caractère point (.) remplace n'importe quel caractère, y compris les nouvelles lignes. Sans cette option, le caractère point ne remplace pas les nouvelles lignes. Cette option est équivalente à l'option Perl /s. Une classe de caractères négative telle que [^a] acceptera toujours les caractères de nouvelles lignes, indépendamment de cette option.
sebmafate
Messages postés4936Date d'inscriptionlundi 17 février 2003StatutMembreDernière intervention14 février 201437 18 oct. 2005 à 16:26
euh... je crois que tu interprètes mal la regex...
on reprend :
(<li>\s*) : <li> suivi de n'importe quel caractères d'espacement (\t \n \r ...), 0 ou plusieurs fois
<li>.*</li> : .* n'importe quel caractère 0 ou plusieurs fois.
pourrais-tu nous montrer ton code... même si c'est du php...
hansap
Messages postés23Date d'inscriptionvendredi 10 juin 2005StatutMembreDernière intervention19 octobre 2005 18 oct. 2005 à 16:36
alors, en fin de post, je t'ai mis ma fonction en entier... mais elle est mal commentée, el les variables mal nommées pour l'instant, suite a de nombreuses refactorisations...
le principe est le suivant :
ma fonctione recupere une ressource de resultat BDD, et une chaine disant quelle balise va etre "fusionnée" sans oublier le fichier source qui va etre modifié
Ensuite, elle recupere une balise de type : <!--StartFragment --> [testBDD;block = li]
de cette balise, elle extrait le block containeur
elle crée ensuite deux strings : et <\/block>
puis lance la regex posant le pb
function mergeDyn($indexBalise, $resultQuery) {
global $template;
dbgStore("on est dans MergeDyn", TEMPLATEDYN);
$motifBaliseBlock = "\[ *$indexBalise *; *block *= *([[:alnum:]]+) *\]";//ex : "[ balise1; block= toto]"
eregi($motifBaliseBlock, $template, $blockNom);//pas de while, un seul block multiple avec le meme index est géré
//recuperation de la balise correspondante trouvée
$baliseMere = $blockNom[0];
$blockNom = ($blockNom[1]);
$blockDebut = "<" . $blockNom . ">";
$blockFin = str_replace("<", "<\/", $blockDebut);
//extraction du block et céation de la var mergedBlock = ""
//"(?:$blockFin\s*)$blockDebut.*\[ *$indexBalise *; *block *= *$blockNom *\].*$blockFin";//ex : "<li>.\[ *testBDD *; *block *= *([[:alnum:]]+)* *]\].</li>"
$motifBlock = "(\<\/li>\s*)<li>.*\<\/li>";
var_dump($motifBlock);
preg_match($motifBlock, $template, $block);
$block = $block[0];
dbgStore("Bloc de travail : $block", TEMPLATEDYN);
$motifSousBalises = "/\[ *$indexBalise *; *([[:alnum:]_]+) *\]/";
preg_match_all($motifSousBalises, $block, $SousBalises, PREG_SET_ORDER);
//interrogation de la base
$mergedBlock = "";
while ($row = mysql_fetch_array($resultQuery, MYSQL_ASSOC ) ) {
//boucle de duplication par les valeur BDD
$blockEntraitement = $block;
foreach ($SousBalises as $SousBalise) { // ($i = 0; $i < count($tab2Balises); $i++) {
$blockEntraitement = str_replace($SousBalise[0],$row[$SousBalise[1]], $blockEntraitement);
}
$mergedBlock .= $blockEntraitement;
}
//reste a supprimmer la balise mere:
$mergedBlock = str_replace( $baliseMere, "", $mergedBlock);
//var_dump($mergedBlock);
//reinjection dans le template
$template = str_replace($block, $mergedBlock, $template);
}
hansap
Messages postés23Date d'inscriptionvendredi 10 juin 2005StatutMembreDernière intervention19 octobre 2005 18 oct. 2005 à 16:45
par contre, la regex que tu me preopose ne me semble pas bonne :
<!--StartFragment -->
<LI>[testBDD;block = li] nom : [testBDD; nom] et id_outil = [testBDD; descriptif ] , enfin, l'activitée est : [ testBDD ;libele] </LI>
<LI>[testL2P ;block = li] [testL2P; libele] </LI>
est un exemple de code posant probleme :
mon script gere tres bien le premier champ, mais pour le second li, il recupere en meme temps le premier... et mixe le tout...
d'apres ce que tu me propose, il trouverait tres bien le second car precedé d'un <li>
mais pour le premier? qui n'est precédé que d'un ??
c'est pour ca que je penchait vers ce genre de motif :
<li> suivit de tout saut <li> suivit de [testL2P ;block = li] suivit de </li>
si tu voit ce que je veut dire.
malheureusement, je ne sait pas comment coder "tout sauf <li>"
sebmafate
Messages postés4936Date d'inscriptionlundi 17 février 2003StatutMembreDernière intervention14 février 201437 18 oct. 2005 à 16:47
je sais maintenant pourquoi j'ai arrété le php : c'est illisible
en fait, je pense que le pattern tel que tu le renseignes ne fonctionne pas.
$motifBlock = "(\<\/li>\s*)<li>.*\<\/li>";
en php (comme en C, C++, C#, Java...), le \ est un caractère d'échappement... le problème c'est que là tu échappes le s dans \s*) ce qui ne veut plus rien dire.
hansap
Messages postés23Date d'inscriptionvendredi 10 juin 2005StatutMembreDernière intervention19 octobre 2005 18 oct. 2005 à 16:56
pourtant ce motif :
$blockDebut.*\[ *$indexBalise *; *block *= *$blockNom *\].*$blockFin";
fonctionnait tres bien... (si je puit dire)
c pas la faute du php, la c'est mas faute pour la presentation...
j'etait a la bourre, je l'ai progremmé en une soirée (tout un framework svp :))
en note la doc php, d'apres elle, il nedevrait pas y avoir de pb avec \s et \/ (qui fonctionne c'est certain)
Si la chaîne est entourée de guillemets doubles (<VAR>"</VAR>), PHP va comprendre certaines séquences de caractères :
Tableau 11-1. Les caractères spéciaux
<COLGROUP>
<COL>
<COL>
----
Séquence |
Valeur |
----
<VAR>\n</VAR>,
Nouvelle ligne (<VAR>linefeed</VAR>, LF ou 0x0A (10) en ASCII),
----
<VAR>\r</VAR>,
Retour à la ligne (<VAR>carriage return</VAR>, CR ou 0x0D (13) en ASCII),
----
<VAR>\t</VAR>,
Tabulation horizontale (HT ou 0x09 (9) en ASCII),
----
<VAR>\\</VAR>,
Anti-slash,
----
<VAR>\$</VAR>,
Caractère $,
----
<VAR>\"</VAR>,
Guillemets doubles,
----
<VAR>\[0-7]{1,3}</VAR>,
Une séquence de caractères qui permet de rechercher un nombre en notation octale.,
----
<VAR>\x[0-9A-Fa-f]{1,2}</VAR>,
Une séquence de caractères qui permet de rechercher un nombre en notation hexadécimale.
Si vous essayez d'utiliser l'anti-slash sur n'importe quelle autre séquence, l'anti-slash sera affiché dans votre chaîne.
Arthenius
Messages postés1182Date d'inscriptionmercredi 21 janvier 2004StatutMembreDernière intervention 6 septembre 201114 18 oct. 2005 à 17:20
heu
et si au lieu de passer par des expressions reguliere tu faisais un programme a la main a l'ancienne qui te parcourt ton bout de code avec les <li> et que tu extrait exactement ce que tu veux ?????
hansap
Messages postés23Date d'inscriptionvendredi 10 juin 2005StatutMembreDernière intervention19 octobre 2005 18 oct. 2005 à 17:30
ce que j'ai du mal a comprendre, c'est que mon expression me semble juste...
totu d'abord, elle cpature bien ce qu'il faut.
secondement son pb est qu'elle est greedy (gourmande).
hors j'utilise l'option //U qui la rend non gourmande...
ce qui marche d'ailleur... mais par pour l'autre... "/$blockDebut.*\[ *$indexBalise *; *block *= *$blockNom *\].*$blockFin/sU"
= >
"/<li> \[ *testBDD*; *block *= *li*\].* <\/li>/sU"
...
d'ailelur si je fait :
"/$blockDebut.*?\[ *$indexBalise *; *block * = *$blockNom *\].*?$blockFin/s"
j'ai le meme pb, ne serait-ce pas un bug de preg_match?