REGEX Php (aidez-moi)

Fermé
Bilow - 2 mars 2010 à 18:24
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 - 5 mars 2010 à 01:40
Bonjour,

J'ai lu tout un chapitre sur les expressions régulières en PHP (Regex), mais je n'arrive pas à en rédiger une toute bête :

J'aimerais remplacer ces exemples de chaines :

/admin//dossier////
////////////////admin////dossier//////////////////
///admin/dossier//////////


par celles-ci :

admin/dossier

Comment faire ?
Merci d'avance,
Bilow.

Ps : Certain diront qu'il vaut mieux apprendre le regex plutôt que de demander les réponses.
Oui, c'est vrai. Mais ce serait quand-même sympa de m'aider ;)
A voir également:

12 réponses

artragis Messages postés 481 Date d'inscription mardi 12 juin 2007 Statut Membre Dernière intervention 6 avril 2010 146
2 mars 2010 à 18:50
alors je vais essayer de t'expliquer comment marche la régex avant de te la donner :
tu veux : supprimer tout caractère placé avant admin, replacer par un seul "/" tout caractère entre les deux mots et supprimer tout caractère après le mot dossier.
en régex, "tout caractère" s'écrit ".", comme on n'en connait pas le nombre, on va dire "tous les caractères éventuels", en régex éventuel s'écrit "*"
Maintenant, comme on veut conserver les mots, il faut les "capturer", on utilise donc une parentèses pour les capturer.
voici donc la régex :
#^.*(admin).*(dossier).*$#
et pour "remplacer" il faut utiliser la fonction preg_replace();
donc le code général :
$chaine ="\\\\\\\\admin\_\dossier\\\\\\\\\\\\"; //par exemple, il est à noter que le "\" n'apparait que s'il est doublé
$chaine=preg_replace("#^.*(admin).*(dossier).*$#",$chaine);

0
Bonjour,

Merci pour ta réponse.
Mais preg_replace prend 3 paramètres. Ici il n'y en a que deux. Donc cela donne une erreur.

Quel est normalement le deuxième paramètre de cette fonction ?

Merci,
Bilow.
0
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 130
3 mars 2010 à 10:28
Bonjour,


La volonté d’explication de atargis est louable mais il se mélange un peu les pinceaux.

D’abord tu donnes des exemples de chaînes ne comportant que des ’/’ et je crois qu’il faut en rester là dessus.
Si tes chaînes présentent en fait d’autres caractères à éliminer, ce serait à toi de t’apercevoir que tu dois en parler.
Je crois pour ma part que tu ne veux vraiment parler que de chaînes avec des ’/’, or la regex que propose atargis ne va pas car à cause du point elle va réagir sur n’importe quelle chaîne contenant admin et dossier, par exemple «L’administration refusa le transfert de tout dossier».

D’autre part , les caractères dans ces chaînes sont des slashes ’/’, pas des antislashes au comportement particulier.

Il y aussi qu’il met ’^’ et ’$’ en tête et en fin de sa RE et que c'est a priori inutile parce que tu ne dis nulle part que les chaînes traitées se limitent aux exemples que tu as donnés.



Je propose donc la RE suivante
’#/+admin/+dossier/+#U’
Le U est indispensable pour rendre /+ non glouton.

Mais vu ce que tu veux faire, preg_replace n’est pas suffisante, il faut utiliser preg_replace_callback avec une fonction que tu définis toi-même:
function reductslash($ch){
    $ar = split(’/’,$ch);
    return implode($ar,'/');
}



$chaine = ’bla//blabli///admin///dossier////frr//r/’
preg_replace_callback(’#/+admin/+dossier/+#U’,’reductslash’,$chaine)


va donner ’bla//blabliadmin/dossierfrr//r/’
0
Salut Heyquem,

Merci pour ta réponse, mais euh...

Parse error: syntax error, unexpected T_VARIABLE in /customers/bilow.be/bilow.be/httpd.www/test.php on line 9


Avec ce code :

<?php
function reductslash($ch){
    $ar = split(’/’,$ch);
    return implode($ar,'/');
}


$chaine = ’bla//blabli///admin///dossier////frr//r/’;
$chaine=preg_replace_callback(’#/+admin/+dossier/+#U’,’reductslash’,­$chaine);
echo $chaine;
?>


Et l'erreur avec
T_STRING
revient si j'appelle la fonction preg_replace_callback sans le '$chaine=' devant.

Pourquoi ?

Merci ;)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
EDIT : Il y a un tiret en trop dans la fonction preg_replace_callback;
0
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 130
3 mars 2010 à 13:43
En effet, j’ai oublié de faire réceptionner ce que renvoie preg_replace_callback() par une variable:
$rec = preg_replace_callback(....)


Il faut dire que le mauel PHP est mal fait
https://www.php.net/manual/fr/function.preg-replace-callback.php
preg_replace_callback — Rechercher et remplacer par expression rationnelle standard en utilisant une fonction de callback
mixed preg_replace_callback ( mixed $pattern , callback $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )
Il n’est pas dit explicitement que la fonction renvoie le résultat et non pas qu’elle fait la modification ’en place’ sur la chaîne soumise $subject

Quand le programme rencontre la ligne preg_replace_callback(’#/+admin/+dossier/+#U’,’reductslash’,$chaine)
elle lui présente une valeur inattendue, c’est sans doute pourquoi il émet le message “unexpected T_VARIABLE“



Mais je ne suis pas connaisseur de PHP, c e n’est pas le langage que je pratique habituellement. La pratique des regex dans PHP m’intéresse, c’est tout. Donc je commets des erreurs.



Je ne comprends pas de quel tiret tu parles dans preg_replace_callback
Ce serait bien d’être plus précis.
0
Salut,

CCM me rajoute un tiret parce qu'il fait un retour à la ligne. Enfin oublions.

Mais T_VARIABLE est une erreur lorsque je mets une variable devant !
$chaine=preg_replace_callback(...);

Enfin voila...

Merci encore, mais je cherche toujours un code qui fonctionne :(

Bye.
0
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 130
3 mars 2010 à 18:51
Ben quand tu auras trouvé, dis moi le truc, parce qu’en regardant les docs, je ne vois pas ce qu’il faut comprendre d’autre.



Par exemple dans cette page,
http://www.expreg.com/pregcallback.php</code>

il y a pas mal d’exemple, et on voit bien des instructions du genre
$image=preg_replace_callback('`(\w*?)(\d+)?(\.jpg)`','ajoute',$image);




<?php
$image="image125.jpg";

function ajoute($masque)
{
return $masque[1].($masque[2]+1).$masque[3];
}

$image=preg_replace_callback('`(\w*?)(\d+)?(\.jpg)`','ajoute',$image);

echo $image;
?>
0
artragis Messages postés 481 Date d'inscription mardi 12 juin 2007 Statut Membre Dernière intervention 6 avril 2010 146
3 mars 2010 à 20:23
oui, en effet j'avais oublié un paramètre
juste une question, pourquoi $chaine=preg_replace(#/*(admin)/*(dossier)/*#,$1."/".$2,$chaine); ne fonctionnerait pas? pourquoi se compliquer la vie avec un callback?
0
Alleluia !

Enfin trouvé !

Merci tout le monde, parce que vous m'avez quand-même aidé.

Voici la solution :

<?php
$chaine="//////////////Admin///////////dossier//////////////////";
$chaine=str_replace("\\", "/", $chaine);   // Pour les antislashs, je les transforme en slashs.
$chaine=preg_replace("#/(/)*#", "/", $chaine); // Remplace tout les slash qui apparaissent d'affilé plusieurs fois par un seul.
echo $chaine;
?>


Voila ;) Et ce code fonctionne avec toutes les chaines que j'ai citées au début.

Un grand merci tout le monde;
Bye.
0
Notes :

Artragis, je ne sais pas pourquoi cela ne fonctionne pas. J'ai essayé, mais cela ne le résout pas.

Enfin bon; C'est résolu (j'ai changé d'IP, je ne sais plus changer le statut de la discussion).

Au revoir ;)
0
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 130
5 mars 2010 à 01:40
juste une question, pourquoi 
$chaine=preg_replace(#/*(admin)/*(dossier)/*#,$1."/".$2,$chaine); 
ne fonctionnerait pas? 
pourquoi se compliquer la vie avec un callback? 


Ça fonctionne, en effet, mais je me suis compliqué la vie parce que je connais mal PHP: je lis les docs avec sérieux mais je ne découvre les choses que peu à peu et j'ignorais ansi la possibilité d'utiliser $1, $2, $3... pour représenter les groupes capturés dans un match.

C'est une possibilité tout à fait intéressante de PHP, qui n'existe pas en Python. Dans ce langage que je connais mieux, quand on veut remplacer par quelque chose qui n'est pas constant mais dépend du match concerné, on doit passer l'objet MatchObject à une fonction qui le décortique pour en extraire les groupes utiles pour le remplacement.

En PHP, il en est autrement et pour le cas de Bilow il est en effet mieux de faire comme tu le dis, artragis:
$chaine=preg_replace(#/*(admin)/*(dossier)/*#,$1."/".$2,$chaine);





Je profite de l'occasion pour signaler cet avis:

Dans une grande majorité de cas, une fonction de type callback sera toujours bien plus rapide que preg_replace() et son option e
Personnellement je déconseille vivement l'emploi de preg_replace() + e.

http://www.expreg.com/asavoir.php</code>



e (PREG_REPLACE_EVAL) 
Avec cette option, preg_replace() effectue la substitution normale des références arrières dans la chaîne de remplacement, puis l'évalue comme un code PHP, et utilise le résultat pour remplacer la chaîne de recherche. Les guillemets simples, les guillemets doubles, les antislashs et les caractères NULL sont protégés avec des antislashs (\) dans les références arrières substituées. 
Seule preg_replace() utilise cette option. Elle est ignorée par les autres.

http://fr2.php.net/manual/fr/reference.pcre.pattern.modifiers.php</code>




Est-ce que ton écriture nécessite l'option e, artragis ?
0