Récupérer une partie d'une chaine

blasterman1
Invité n'ayant pas de compte PHPfrance

02 mai 2006, 15:32

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

Eléphant du PHP | 493 Messages

02 mai 2006, 15:44

Bonjour, et voila :
preg_match( '/^(?:.*_){2}(.*),/', $str, $match );

blasterman1
Invité n'ayant pas de compte PHPfrance

05 mai 2006, 09:49

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)

blasterman1
Invité n'ayant pas de compte PHPfrance

05 mai 2006, 09:52

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

Eléphant du PHP | 493 Messages

05 mai 2006, 10:39

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

blasterman1
Invité n'ayant pas de compte PHPfrance

05 mai 2006, 13:41

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];

Eléphant du PHP | 493 Messages

05 mai 2006, 13:42

Je ne peux que te conseiller d'effectuer un
print_r( $match );
pour voir de quoi il en retourne !

blasterman1
Invité n'ayant pas de compte PHPfrance

05 mai 2006, 15:51

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

Modérateur PHPfrance
Modérateur PHPfrance | 6037 Messages

05 mai 2006, 16:10

$match n'a pas de case $match[1] c'est pour cela que tu as une erreur.
Règle n°2 du webmaster : Toujours commencer par le HTML qu'on veut obtenir....toujours ! :priere:
J'aime apprendre de nouvelles choses.

Invité
Invité n'ayant pas de compte PHPfrance

09 mai 2006, 09:22

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

ViPHP
ViPHP | 1380 Messages

09 mai 2006, 09:47

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
ripat