Une petite aide sur une expression reguliere svp :))

[Résolu]
Signaler
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005
-
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005
-
http://www.developpez.net/forums/viewtopic.php%3Ft%3D406330%26start%3D15' target='_blank'>http://www.developpez.net/forums/viewtopic.php?t=406330&start=15
si vous voulez bien m'aider... :)

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 ))

25 réponses

Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

Ca marche !!!!


"/<li>(.(?<!<li>))*\[ *testBDD *; *block *= *li *\].*<\/li>/sU"


telle est le type de motif qui fonctionne!
en versino simplifée :


"/<li>(.(?<!<li>))*.*<\/li>/sU"


MERCI A TOUS!!!!
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
celle-ci fonctionne : (?:</li>\s*)<li>.*</li>

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

ca me retrourne l'erreure suivante :

<!--StartFragment --> Warning: Unknown modifier '<' in f:\action1 framework\index.php

peut tu m'expliquer :
(?:</li>\s*)

ca veut dire :
pas de </li> 0..n fois, suivit de <li>.*</li>
?

donc () indique une suite de char,
?: ->une negation
/s ->retours a la ligne possible
* -> 0..n fois

c'est bien ca?
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
?: --> c'est non capture... mais ce n'est peut-être pas géré en php...

essaye : (</li>\s*)<li>.*</li>

et n'oublie pas de doubler les \ dans sinon ca marche pas !

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

ps : j'utilise preg_match, utilisant PCRE "Expressions rationnelles compatibles Perl"

la notation est-elle la meme que celleque tu utilise?
utuilise tu POSIX?
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
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 >

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

j'ai donc testé

<!--StartFragment --> (\<\/li>\s*)<li>.*\<\/li>

ca ne passe pas, toujours : <!--StartFragment --> Warning: Unknown modifier '<' in f:\action1 framework\index.php

bizaremment, quand j'utilisait :

"/<li>.*\[ * TESTBDD *; *block *= *<li> *\].*<\/li>/sU"

ca ne me mettait pas cette erreure....

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)
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
essaye ca : (</li>\\s*)<li>.*</li>

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

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.

??

</DD>
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
39
Ohlala vous allez finir pour vous grillez des neurones avec vos expressions régulières
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
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...

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

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);
}
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

a retenir :
$motifBlock = "(\<\/li>\s*)<li>.*\<\/li>";

preg_match($motifBlock, $template, $block);

ps : j'ai fait une erreure : [testBDD;block = li]
(testBDD n'est pas "en vert")
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

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>"

(^<li>) => ?? ne semble pas marcher...
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
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.

Essaye ceci : $motifBlock = "(</li>\\s*)<li>.*</li>";

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

il n'a pas prise mes liste, je reprend :

<li>
[testBDD;block = li]
nom : [testBDD; nom] et id_outil =&nbsp;[testBDD; descriptif ] , enfin, l'activitée est : [ testBDD ;libele]
</li>

<li>
[testL2P ;block = li]
[testL2P; libele]
</li>
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
sinon, la regex standard pour récupérer toutes les lignes de <li>

<li>(.*?)</li>

à toi maintenant de vérifier ce qu'il s'y trouve

Sébastien FERRAND
[MVP C#]
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

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.
Messages postés
1182
Date d'inscription
mercredi 21 janvier 2004
Statut
Membre
Dernière intervention
6 septembre 2011
14
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 ?????

en testant les caracteres.. ??




<HR>
Arthenius
http://blogs.developpeur.org/Arthenius/

"Ce qui ne me tue pas, me rend plus fort..."
Messages postés
23
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
19 octobre 2005

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?