Regexp embetante

jules
Invité n'ayant pas de compte PHPfrance

26 déc. 2008, 23:38

Bonsoir,

Je suis embêté par une vilaine Regexp.
Je voudrais récupérer le XXX dans ce code html là :

Code : Tout sélectionner

<tr class="black"> <td width="90%"> AAA </td> <td> XXX </td> </tr>
où :
AAA est une chaine de caractère fixe (10 caractères si ça peut aider..)
et XXX est ce que je veux récupérer.

J'ai essayé :
preg_match_all("#<td width=\"90%\">(0-9A-Za-z){10}</td><td>(.*)</td>#s", $page, $bordel);
J'ai ajouté l'option "s" pour que le CRLF soit inclu.
Mais évidement mon tableau $bordel est vide..

Merci pour votre aide.

jules
Invité n'ayant pas de compte PHPfrance

26 déc. 2008, 23:39

J'ai oublié de préciser à ceux qui pourraient me dire "récupère ce qu'il y a entre <td> et </td>" que des <td> il y en a plein la page.. :s

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

27 déc. 2008, 01:59

Hmmm... tu n'as pas bien compris le fonctionnement de l'option "s" dans les expression régulières. Elle ne permet pas d'ignorer les retours à la ligne, mais de dire que le caractère "." qui remplace n'importe quel caractère, peut également remplacer les retours à la ligne. Ca ne t'empêche pas de devoir le spécifier dans ton masque :)
preg_match_all("#<td width=\"90%\">([0-9A-Za-z]{10})</td>.*<td>(.*)</td>#s", $page, $bordel);
J'en ai profité pour réajuster parenthèses et crochets autour de la chaine AAA, mais ne connaissant pas le besoin ou la structure de la chaine, ce sera sans doute à revoir :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 1339 Messages

27 déc. 2008, 01:59

<?php

$code = '<tr class="black">
     <td width="90%"> AAA </td>
     <td> XXX </td>
</tr>';

preg_match_all("#<td>(.*)</td>#s", $code, $bordel);

print_r($bordel[1][0]);
            

?> 
Tout simplement :)

Je suppose que il y aura une condition que j'aurais pas pris en compte :)
Bon sinon tu me fais un message privé et on se fait un TeamViewer

jules
Invité n'ayant pas de compte PHPfrance

27 déc. 2008, 03:35

Tout simplement :)
Je suppose que il y aura une condition que j'aurais pas pris en compte :)
Oui, car ma variable "$code" contient toute une page en réalité avec plein de <td>..
preg_match_all("#<td width="90%">([0-9A-Za-z]{10})</td>.*<td>(.*)</td>#s", $page, $bordel);
Merci bien pour ton aide et la précision (importante!) pour l'option 's'.
Cela ne fonctionne toujours pas. J'ai essayé de mettre le 'vrai' texte à la place de ([0-9A-Za-z]{10}) pour voir si l'erreur venait de là ou pas, et effectivement mon tableau est toujours vide
(expression de test :
preg_match_all("#<td width="90%">abcdefghio</td>.*<td>(.*)</td>#s", $page, $bordel);
Le tableau de sortie est vide, pourtant ca l'air de coller :/

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

27 déc. 2008, 12:33

euh.... t'as modifié le masque là.... en gros, tu dis que tu cherches une chaine avec "abcdefghio" dans ton code, et pas avec 10 caractères quelconque pour le "AAA" ....

Est-ce que tu pourrais nous donner un ou deux exemple du code original (celui que tu veux récupérer). Juste les zones concernées, mais avec les vraies valeurs à la place des AAA et XXX :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 170 Messages

27 déc. 2008, 13:00

Code : Tout sélectionner

<tr class="black"> <td width="90%"> AAA </td> <td> XXX </td> </tr>
où :
AAA est une chaine de caractère fixe (10 caractères si ça peut aider..)
(0-9A-Za-z){10}
Il y a 2 espaces qui encadrent la fameuse chaîne de caractères ...
... et ils n'apparaissent pas dans le motif de l'expression régulière.

Je ferais quelque chose comme ça :
<pre>
<?php

$page = '<tr class="black">
     <td width="90%">abcdefghio</td>
     <td> XXX </td>
     <td> aaa </td>
     <td> bbb </td>
</tr>';

preg_match_all('#<td width="90%">[0-9A-Za-z ]{10}</td>.*<td>(.*)</td>#Us', $page, $v); 

//echo $v[1][0];
print_r($v);
?>
</pre>
( sans l'option U ( ungreedy / non gourmand ), et avec ce motif, ça ne marche pas )

et si il y a une seule valeur à récupérer, il vaut mieux utiliser preg_match() plutôt que preg_match_all().

Invité
Invité n'ayant pas de compte PHPfrance

27 déc. 2008, 16:09

Merci bien pour code blof, effectivement avec ton code cela fonctionne bien, avec

Code : Tout sélectionner

<td width="90%">abcdefghio</td>
(c.a.d collé aux balises) mais PAS avec un espace avant et apres la chaine comme j'avais écrit :

Code : Tout sélectionner

<td width="90%"> abcdefghio </td>
Voici un exemple concret Ryle :

Code : Tout sélectionner

<tr class="black"> <td width="90%"> C1C93AA443 </td> <td> Petit_Atelier </td> </tr>
(ce sont des références)

Pourquoi le masque #<td width="90%">[0-9A-Za-z ]{10}</td>.*<td>(.*)</td>#Us
ne prend-il pas en compte l'espace pourtant spécifié ?

Eléphant du PHP | 170 Messages

27 déc. 2008, 16:55

Pourquoi le masque #<td width="90%">[0-9A-Za-z ]{10}</td>.*<td>(.*)</td>#Us
ne prend-il pas en compte l'espace pourtant spécifié ?
parce qu'il y a 12 caractères entre les balises "td" :wink:

donc soit :
#<td width="90%">[0-9A-Za-z ]{12}</td>.*<td>(.*)</td>#Us
soit :
#<td width="90%"> [0-9A-Za-z]{10} </td>.*<td>(.*)</td>#Us
( dans ce cas il ne doit pas y avoir d'espace dans la chaîne )

jules
Invité n'ayant pas de compte PHPfrance

07 janv. 2009, 20:45

Re,

Désolé, aucun des deux masques ne fonctionne. Mon tableau reste vide :/

jules
Invité n'ayant pas de compte PHPfrance

07 janv. 2009, 21:07

Je vois pourquoi..
Y'a des tabulations avant ma référence, ce qui est invisible quand je le copie colle ici.
en gros ca fait :
<td width="50%">
(saut à la ligne)(6 tabulations)abcdefijre
(saut à la ligne)(5 tabulations)</td>

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

08 janv. 2009, 12:25

Ben tu as la réponse à ta question... le masque s'applique à la chaine telle qu'elle présente dans le fichier source, il te faut donc faire un masque qui prenne en compte les retours à la ligne, les tabulations et les espaces éventuels :)

Si tes sauts de lignes sont toujours au même endroit, et que tu as toujours le même nombre de tabulations, tu peux les ajouter dans ton masque caractère par caractère (au début et à la fin, en fait partout où tu en a besoin :)).

Tu peux aussi spécifier le nombre d'occurence de la tab si celui-ci varie : "\t{0,6}" pour en avoir de 0 à 6 et éviter de le répéter 6 fois alors qu'il pourrait n'y en avoir que 5 de temps à autre etc.

Enfin, tu peux également utiliser la classe [[:space:]] dont je te laisse le soin de découvrir les effets et l'intéret dans ton cas :)

D'une manière générale, les expressions régulières ne sont pas bien compliquées à mettre en oeuvre, il te faut simplement trouver le masque qui colle parfaitement à ta chaine, et ce en toute circonstance :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

jules
Invité n'ayant pas de compte PHPfrance

10 janv. 2009, 00:21

Merci pour tes conseils !

Alors j'ai essayé :
- avec la classe :space: qui englobe d'après ce que j'ai lu les \r \n et \t
preg_match_all('#<td width="90%">[[:space:]]*[0-9A-Za-z]{10}[[:space:]]*</td>[[:space:]]*<td>(.*)</td>#Us ', $page, $bordel);  
- et la manière statique, en précisant le nombre exact de tabulations
preg_match_all('#<td width="90%">\r\n\t\t\t\t\t\t[0-9A-Za-z]{10}\r\n\t\t\t\t\t</td>\r\n\t\t\t\t\t<td>(.*)</td>#Us ', $page, $bordel);  
Mais aucun des deux masques n'est valide. Peut etre que je les utilise mal ?!
J'ai vu aussi que dans certains codes des personnes utilisent les codes hexadécimaux (comme 09 pour \t) dans leurs masques. Ca n'avait pas l'air de changer quoique ce soit pour moi..

Eléphant du PHP | 170 Messages

10 janv. 2009, 10:06

Salut,

bientôt 15 jours ...
... c'est trop.

Peux-tu faire un vrai copié/collé de ta chaîne de caractères ?
( ne saisis pas de mémoire ce que tu penses que ça pourrait éventuellement être. )

jules
Invité n'ayant pas de compte PHPfrance

10 janv. 2009, 12:25

Lut,
Voilà donc un vrai copié/collé,
Les sauts à la ligne ont été gardés, j'ai donc rajouté ce qui avait disparu : les tabulations.

Code : Tout sélectionner

<td width="90%"> (6 tabulations) AX2987HH00 (5 tabulations) </td> (5 tabulations) <td> (5 tabulations) Epautre_C6 (5 tabulations) </td>
Et au final je coudrais récupérer "AX2987HH00 => Epautre_C6"
Merci