IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Regex avec condition [RegEx]


Sujet :

Langage PHP

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 8
    Points : 3
    Points
    3
    Par défaut Regex avec condition
    Bonsoir !

    Je suis sur une regex qui me casse la cabeza... Je suis pas un pro des expressions régulières, mais j'arrive toujours à m'en sortir et finalement à trouver.

    Hors, celà fait 2 jours que je pense qu'à celle là, et là ca devient trop obsessionnelle, donc j'ai besoin d'aide ^^.

    Voici un panel d'exemple de string cible :

    <a href="http://www.lebon.com/test/de/accueil/index.html>
    <a href="http://www.lebon.com/fr/accueil/index.html>
    <a href="http://www.lebon.com/accueil/index.html>
    <a href="test/it/accueil/index.html>
    <a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html>
    <a href="images/accueil/index.html>
    <a href="http://www.lemauvais.com/test/de/accueil/index.html>

    J'aimerais donc modifier le mot accueil en home. Mais j'ai plusieurs conditions :

    - si http dans le href alors que http://www.lebon.com
    - accueil est forcément précéde de : /(de?|es?|it?|nl?|pt?|gb?|fr?)/
    - si il y a un mot dans le href commencant par imag* je ne prends pas en compte.

    Dans mes exemples les n° 1, 2, et 4 sont bons pas les autres.

    J'ai commencé par essayer de faire un match et de voir ensuite comment prendre qu'une partie :

    <a href="(http://www.lebon.com/?)(.*)/(:?fr?|gb?|de?|es?|it?|nl?|pt?)/accueil/

    Mais çà m'a embrouillé plus qu'autre chose et je tourne en rond :s

    Si un regex guru passe par là et a du temps ca me ferait bien plaisir ^^


    Merci beaucoup !

    Yudao.

  2. #2
    Membre éclairé Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Points : 718
    Points
    718
    Par défaut
    Visiblement tu n'as pas donné toutes les conditions car la 5 répond à tes conditions mais tu dis qu'elle est fausse

    Sinon je pense que ça fera l'affaire même si ça consomme 3 regex.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    function preg_match_all_callback($regex, $callback, $string, &$result)
    {
    	preg_match_all($regex, $string, $matches);
     
    	foreach($matches as $match)
    	{
    		if (call_user_func($callback, $match))
    		{
    			$result[] = $match;
    		}
    	}
    }
     
    function test_string($match)
    {
    	// Si on trouve http:// non suivi de www.lebon.com
    	// Si on trouve acceuil non précédé de /de/ ou /es/ ou /it/ ou /nl/ ou /pt/ ou /gb/ ou /fr/
    	// Si on trouve un mot (\b) qui commence par imag
    	// On retourne FALSE (faux)
    	if( preg_match('#http://(?!www.lebon.com/)#', $match[1]) || preg_match('#(?<!/(de|es|it|nl|pt|gb|fr)/)acceuil#', $match[1]) || preg_match('#\bimag#', $match[1]) )
    	{
    		return FALSE;
    	}
     
    	return TRUE;
    }
     
    preg_match_all_callback('#<a href="(.*)"#Ui', 'test_string', $chaine, $matches);

  3. #3
    Membre habitué Avatar de daniel61
    Inscrit en
    Décembre 2006
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 139
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par yudao
    Je suis sur une regex qui me casse la cabeza... Je suis pas un pro des expressions régulières, mais j'arrive toujours à m'en sortir et finalement à trouver.
    il n'y a pas de mal à découper un problème comme te le propose Korko Fain. mon choix personnel irait vers preg_replace_callback() puisque c'est un cas de remplacement.

    Citation Envoyé par yudao
    Hors, celà fait 2 jours que je pense qu'à celle là, et là ca devient trop obsessionnelle
    oui, ça peut se faire en 1 regex. je vais te proposer quelque chose pas nécessairement agréable pour les neurones par contre.

    Citation Envoyé par yudao
    <a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html">
    je vais supposer que accueil n'est pas remplacé parcequ'il n'est pas le dernier répertoire.

    Citation Envoyé par yudao
    <a href="
    href précédé d'un espace me semble suffisant et il faut considérer la possibilité d'espaces autour de = le caractère ' peut aussi être utilisé pour délimiter le lien.

    \shref\s*=\s*([\'"]) en capturant le caractère ' ou " la regex pourra utiliser cette capture pour reconnaitre la fin du lien.

    Citation Envoyé par yudao
    (http://www.lebon.com/?)
    la torture des neurones commence ici... il existe les assertions dans pcre, une assertion est simplement une validation qui ne capture pas, qui ne déplacement pas le curseur sur la chaine source, mais qui fait un test sur les caractères suivants ou précédants le curseur. il y a plusieurs types d'assertions, et pour ce premier éléments il faudra 2 assertions, une conditionnelle et si elle est vrai alors une avant positive complètera le travail.

    (?(condition)pattern__si_vrai|pattern_si_faux) est la forme d'une conditionnelle. la condition doit obligatiorement être une assertion, le "pattern_si_faux" est optionnel...

    (?=caractères) est la forme d'une avant positive, l'assertion teste si les caractères suivants le curseur sont identiques... sans déplacer le curseur.

    (?(?=http://)(?=http://www.lebon.com)) revient à dire que si les caractères suivants " ou ' sont http:// alors poursuivre si et seulement si les caractères suivant " ou ' sont http://www.lebon.com et il n'y a aucun besoin d'un "pattern_si_faux". les assertions ne déplacent pas le curseur, mais comme il n'y a pas de condition en conflit, pas besoin de forcer le déplacement.

    Citation Envoyé par yudao
    (.*)
    j'imagine que tu voulais garder la négation de imag* pour la fin... un mot commencant par imag peut s'écrire avec imag précédé par \b qui est une classe de caractère particulère puisqu'une assertion... \b représente tous les caractère non alphanumérique en excluant aussi le caractère _ qui est membre de la classe \w. la forme de la négation d'une séquence de caractère est (?!caractères) mais c'est aussi une assertion, donc ça ne déplace pas le curseur sur la chaine source... il faudra utiliser le méta-caractère . avec un sous-masque pour forcer le déplacement.

    (?:(?!\bimag).)+? permet de parcourir en ungreedy le contenu de href et d'arrêter si un mot débutant par imag est rencontré.

    Citation Envoyé par yudao
    /(:?fr?|gb?|de?|es?|it?|nl?|pt?)
    pt? a pour effet de permettre 0 ou 1 fois le t seulement. la répétition évidente est {1} puisqu'il faut toujours une fois un et un seul des éléments de l'énumération.
    /(?:de|es|it|nl|pt|gb|fr){1}

    maintenant, il est temps de faire la capture en \\1 de ce qui précéde /accueil/ pour pouvoir faire une remplacement \\1/home/...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (\shref\s*=\s*([\'"])(?(?=http://)(?=http://www.lebon.com))(?:(?!\bimag).)+?/(?:de|es|it|nl|pt|gb|fr){1})/accueil/
    si jamais il doit y avoir remplacement de /accueil/ dans <a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html"> alors la regex est complète et tu pourras aussi enlever la capture sur ([\'"]) parceque non nécessaire.

    par contre, s'il faut faire le remplacement de /accueil/ seulement si c'est le dernier répertoire, alors il faudra faire une capture en \\3 de la suite si valide bien entendu.

    ([^/]+?\2) revient à nier le caractère / jusqu'au caractère qui aura été capturé en \\2... le fameux ([\'"]), donc si c'était " alors \2 contiendra ", et si c'était ' alors \2 contiendra '. si un caractère / est rencontré, alors le regex se terminera et aucun remplacement ne sera fait... le tout capturé en \\3 puisque \\2 contient le caractère délimitant le lien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    $html='
    <a href="http://www.lebon.com/test/de/accueil/index.html">
    <a href="http://www.lebon.com/fr/accueil/index.html">
    <a href="http://www.lebon.com/accueil/index.html">
    <a href="test/it/accueil/index.html">
    <a href="jessaye/nimportequoi/test/pt/accueil/patati/patata/kaisoif.html">
    <a href="images/accueil/index.html">
    <a href="http://www.lemauvais.com/test/de/accueil/index.html">
    ';
     
    $resultat=preg_replace('#(\shref\s*=\s*([\'"])(?(?=http://)(?=http://www.lebon.com))(?:(?!\bimag).)+?/(?:de|es|it|nl|pt|gb|fr){1})/accueil/([^/]+?\2)#is','\\1/home/\\3',$html);
    echo htmlentities($resultat);

  4. #4
    Membre éclairé Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Points : 718
    Points
    718
    Par défaut
    Ce n'est pas \\2 plutot que \2 ?
    Sinon, tres tres bon descriptif. A garder sous le coude ^^

  5. #5
    Membre habitué Avatar de daniel61
    Inscrit en
    Décembre 2006
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 139
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par Korko Fain
    Ce n'est pas \\2 plutot que \2 ?
    des équivalences. je préfère \2 dans l'expression et \\2 dans la chaîne de remplacement.

  6. #6
    Membre éclairé Avatar de Korko Fain
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    632
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 632
    Points : 718
    Points
    718
    Par défaut
    Ok je connaissai les équivalences \\2 et $2 mais pas \2 ^^

    De plus, le {1} n'est pas nécéssaire puisqu'il est compté par défaut...

  7. #7
    Membre habitué Avatar de daniel61
    Inscrit en
    Décembre 2006
    Messages
    139
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 139
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par Korko Fain
    De plus, le {1} n'est pas nécéssaire puisqu'il est compté par défaut...
    exact

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 08/06/2004, 14h51
  2. Sélection multi table avec condition
    Par iuz dans le forum Langage SQL
    Réponses: 8
    Dernier message: 05/05/2004, 15h04
  3. ALTER VIEW avec condition
    Par yan77 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/04/2004, 17h22
  4. Index avec conditions
    Par marhnix dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 29/03/2004, 10h48
  5. boucle avec condition d'arret changeante
    Par NicoH dans le forum Langage
    Réponses: 3
    Dernier message: 10/06/2003, 11h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo