Page 1 sur 1

Récupérer une partie d'une chaine

Posté : 02 mai 2006, 15:32
par blasterman1
Bonjour
j'aimerais couper une chaine de caractère pour récupérer une partie comptant entre 2 et 4 caracteres selon l'adresse donnée....
En fait, j'aimerais récupérer à partir du 2eme _ jusqu'à la virgule
exemple: CN=GG_elp_tc,OU=FORMATIONS

Merci à l'avance

Posté : 02 mai 2006, 15:44
par Vaedan
Bonjour, et voila :
preg_match( '/^(?:.*_){2}(.*),/', $str, $match );

Posté : 05 mai 2006, 09:49
par blasterman1
Re-bonjour
je m'excuse de répondre si tard après la réponse, mais ca ne marche tjrs pas, j'ai essayer plusieurs facons mais j'ai tjrs le problème d'avoir la virgule ainsi qu'une lettre si le code a 2 lettres
ex: _tc,OU=
Pourrais-tu m'expliquer la forumle car j'ai chercher sur le net et l'explication est compliquée (pour moi au moins)

Posté : 05 mai 2006, 09:52
par blasterman1
Je vais au moins mettre le vrai chemin pour les caractères à aller chercher
"memberof=CN=GG_edt_tc1,OU=FORMATIONS,DC=ad-peda,DC=univ-nancy2,DC=fr";

(Apres le 2 eme underscore et avant la 1 ere virgule

Posté : 05 mai 2006, 10:39
par Vaedan
Bonjour, tu as raison, je suis allé un peu vite. Je vais détailler :)

Un expression régulière PCRE (pour preg et non ereg) doit être encadrée. Ici j'ai utilisé des slashes / mais j'aurais très bien pû mettre un #, cela ne change rien !
/expression/ ou #expression#
L'accent circonflexe (hu ?) ^ indique que l'expression doit commencer à chercher au début de la chaîne.

Ensuite ce trouve un sous-masque. Ce dernier permet d'identifier des parties de l'expression sans les considérer comme des parties recherchées. Il a les même propriété que le masque 'simple' basé avec les parenthèses.
/^(?:debut)/
Vient après le point . qui désigne "n'importe quel caractère". Il sert de Joker. L'étoile * indique que le caractère précédent peut être répété à l'infini, ou pas ! Ainsi la combinaison .* permet de "sélectionner" toute l'expression jusqu'à la prochaine condition.

J'ai par la suite ajouté l'underscore _. L'expression recherchée est donc une chaine quelqueconque suivie d'un underscore.
/^(?:.*_)/
Ici s'achève le sous masque. L'idée est de répéter ce motif puisque ta variable est de la forme xxx_yyy_qqch. L'ajout de {n} permet de répéter le motif précédent n fois. Ici le motif est un sous-masque. Il sera donc répété 2 fois. Actuellement notre petit regex identifie xxx_yyy_. Il ne reste plus qu'à récupérer la fin.

Cette fois-ci on utilise un masque et non-plus un sous-masque, afin de demander à PHP de garder en mémoire ce qu'il va "trouver" via preg_match(). La synthaxe d'un masque est
/(masque)/
On va une fois de plus avoir recours à un Joker .*. Seulement voila, ce n'est pas fini ! Si on arrête pas la recherche par une autre condition, ici la virgule, tout sera sélectionné. Ainsi notre expression finale devient
/^(?:.*_){2}(.*),/
Maintenant que nous avons l'expression, il nous faut l'appliquer via preg_match().
preg_match( '/^(?:.*_){2}(.*),/', $str, $match );
Si quelquechose est trouvé, nous devons l'extraire ! Et ce de la manière suivante :
$var = $match[1][0];
La première colonne correspond à l'aboutissement du regex, la deuxième aux résultats.

Il y a 2 lignes dans la première colonne :
  • $match[0] : chaine de base$match[1] : chaines trouvées
Nous nous rendons donc dans la deuxième colonne afin de récupérer les morceaux extraits par notre regex. Cette colonne contient ici un seul résultat puisque nous n'avons qu'un seul masque. Le sous-masque ne figure pas dedans. Donc :
// première colonne, deuxième ligne
// $match[1]

// deuxième colonne, première ligne
// $match[1][0]
J'espère avoir été assez clair ;)

Posté : 05 mai 2006, 13:41
par blasterman1
Merci bcp pour l'explication,
cependant il reste tjrs un erreur par rapport à la récupération de la chaine coupée
Notice: Undefined offset: 1 in c:\install pl\easyphp1-8\www\ldap\copie de ldap.php on line 133

Ligne 133: $prog = $match[1][0];

Posté : 05 mai 2006, 13:42
par Vaedan
Je ne peux que te conseiller d'effectuer un
print_r( $match );
pour voir de quoi il en retourne !

Posté : 05 mai 2006, 15:51
par blasterman1
il me retourne
Array ( [0] => CN=GG_edt_ogp1,OU=FORMATIONS,DC=ad-peda,DC=univ-nancy2,................... (22 fois du a ma boucle crée plus haut)
Dans le fond, il ne récupère aucunement une partie de l'adresse comme voulue

Posté : 05 mai 2006, 16:10
par mere-teresa
$match n'a pas de case $match[1] c'est pour cela que tu as une erreur.

Posté : 09 mai 2006, 09:22
par Invité
Merci pour l'aide
Après avoir changeé le print() voici ce qui s'affiche:
ogp2,OU=FORMATIONS,DC=ad-peda,DC=univ-nancy2
Donc la partie avant la chaine voulue a été supprimé, mais j'aimerais aussi que la partie après la virgule soit supprimé. Je ne sais pas si cela peut se faire dans le même preg_match ou je dois faire une deuxieme recherche

Posté : 09 mai 2006, 09:47
par Ripat
La gourmandise est un vilain défaut! :wink:

Pour reprendre le motif de Vaedan, il faut rendre le quantificateur non gourmand:

Code : Tout sélectionner

#^(?:.*_){2}(.*?),#
Sans le *?, le moteur regex continuera jusqu'à la dernière virgule du texte soumis.

Ou, autrement:

Code : Tout sélectionner

#^(?:[^_]*_){2}([^,]*)#
Les classes négatives [^,] et [^_] veulent dire tout caractère à l'exception de la virgule (ou underscore). Dans ce cas, le moteur regex s'arrêtera dès qu'il rencontrera la première virgule. Il n'ira pas plus loin. Pas besoin, ici, de rendre le quantificateur * non gourmand.

L'avantage des classes négatives de caractères est qu'elles sont plus rapides. Plus de deux fois plus rapide dans ton cas.

Tu peux voir ces deux motifs à l'oeuvre, dans ce testeur