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 :

Recupérer lien pour mot précis [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Inscrit en
    Décembre 2008
    Messages
    483
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 483
    Points : 105
    Points
    105
    Par défaut Recupérer lien pour mot précis
    Bonjour,

    J'aimerai récupérer le lien contenu dans un suivant le mot entre les 2 balises.

    Je m'explique : si je cherche le mot 'coucou' et quand dans mon texte j'ai :

    <a href="developpez.com?id=12543">coucou je suis un forumeur</a>
    j'aimerai récupérer l'url developpez.com?id=12543. En gros en mots français ça donnerai :

    Récupère l'url du lien si tu trouve le mot à rechercher entre les balises.

    PS : j'utilise en général des preg_match

  2. #2
    Membre régulier
    Inscrit en
    Décembre 2008
    Messages
    483
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 483
    Points : 105
    Points
    105
    Par défaut
    Cela donnerai un truc du genre ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match("/<a href(.*?)<\/a>/si", "", "texte");
    Avec ça il me récupère un lien html, mais il faudrait spécifier dans le regex qu'il y ai "coucou" par exemple.

  3. #3
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Bonjour,


    Tout ça est du grand n’importe quoi:

    Tu fais une exposition entortillée du problème de base auquel les regex répondent.

    Par dessus le marché tu donnes des exemples qui n’ont rien à voir avec la description de preg_match:
    preg_match ( $pattern , $subject [, &$matches [, $flags [, $offset ]]] )
    http://fr2.php.net/manual/fr/function.preg-match.php


    En exprimant ton objectif de façon simple, ça donne
    Extraire une url d’un motif de balise contenant le mot ’coucou’
    C’est la définition d’une recherche par regex tout à fait triviale.


    Dès lors ceci devrait marcher
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '#<a href="(.+)">.*coucou.*</a>#U'


    Je te conseillerais la chose suivante quand tu cherches une RE: dis toi que tu cherches à écrire la description d’un motif, et non pas que tu cherches à décrire les actions que doivent être faites par le moteur de regex.



    Enore une chose à propos de
    PS : j'utilise en général des preg_match
    Peu importe. On doit utiliser des outils pour obtenir une résolution donnée, et non pas adapter une résolution en fonction d’un outil.

  4. #4
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 640
    Points : 66 665
    Points
    66 665
    Billets dans le blog
    1
    Par défaut
    je preconise plutot

    pour des raisons de performances ...

  5. #5
    Membre régulier
    Inscrit en
    Décembre 2008
    Messages
    483
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 483
    Points : 105
    Points
    105
    Par défaut
    merci

    j'essaie de récupérer du texte qui se situe entre 2 liens où dans le 1er j'aurai par exemple 'coucou'.

    Ça ferait ceci ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '#<a href="([^"]+)">.*coucou.*</a>(.+)<a href=#Ui'
    J'ai repris mon regex précédent, en rajoutant à la suite


  6. #6
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Il suffit d’essayer , non ?
    Soit tu l’as fait et le résultat te convient , et dans ce cas on se demande quel est le problème. Ou alors le résultat ne te convient pas, et alors pourquoi ne pas préciser ce qui ne va pas ?
    Soit tu ne l’as pas fait, et ce serait pour le coup carrément bizarre.


    Ce que je peux dire se limite à ceci:
    s’il n’y a pas de fin de ligne entre </a> et <a href= , ta regex fera ce que tu cherches à obtenir.



    Soit dit en passant, pourquoi écrire “mon regex“ alors qu’ expression est un mot féminin ??

  7. #7
    Membre régulier
    Inscrit en
    Décembre 2008
    Messages
    483
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 483
    Points : 105
    Points
    105
    Par défaut
    Oui j'essaie.

    Oui il peut y avoir des sauts de lignes. Il suffit alors seulement de rajouter le 's' à la fin ?

    '#<a href="([^"]+)">.*coucou.*</a>(.+)<a href=#Uis'

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	$text = '<a href="lien.html">coucou</a>';
    	 preg_match('#<a href="([^"]+)">.*coucou.*</a>#Uis', $text, $desc);
    	echo $desc[1];
    m'affiche bien le lien que je souhaite (lien.html)

    alors que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	$text = '<a href="lien.html">coucou</a>azerty<a href=...';
    	 preg_match('#<a href="([^"]+)">.*coucou.*</a>(.+)<a href=#Uis', $text, $desc);
    	echo $desc[1];
    je ne parviens pas à avoir 'azerty'

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 78
    Points : 62
    Points
    62
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	$text = '<a href="lien.html">coucou</a>azerty<a href=...';
    	 preg_match('#<a href="([^"]+)">.*coucou.*</a>(.+)<a href=#Uis', $text, $desc);
    	echo $desc[1];
    principe du preg_match :
    dans la première case (numéro 0), il te met toute la chaine capturée, dans la seconde (numéro 1), ce qu'a capturé la première parenthèse capturante (ici href="([^"]+)" donc lien.html), dans la troisième (numéro 2), ce qu'a capturé la deuxième parenthèse capturante (ici (.+) donc azerty) etc.

    ici, tu fais donc afficher ta première parenthèse capturante donc "lien.html". Si tu veux azerty il te faut faire echo $desc[2]

    je ne voudrais pas dire de bêtises donc dites-moi si je me trompe, mais si le motif peut être présent plusieurs fois dans ta page, il va falloir que tu fasses un preg_match_all pour pouvoir récupérer tous les cas.
    voici comment sera construit le tableau du preg_match_all pour le cas suivant :
    chaine testée :
    <a href="lien.html"> dsqcoucou
    dsq</a>azerty
    <a href=...
    <a href="lien.html">coucou</a>niark<a href=...
    <a href="lien.html">plop</a>huhu<a href=...
    <a href="lien.html">coucou</a>
    azerty<a href=...
    résultat :
    [0]=> array
    [0]=><a href="lien.html"> dsqcoucou dsq</a>azerty <a href=
    [1]=><a href="lien.html">coucou</a>niark<a href=
    [2]=><a href="lien.html">plop</a>huhu<a href=... <a href="lien.html">coucou</a> azerty<a href=
    [1]=> array
    [0]=>lien.html
    [1]=>lien.html
    [2]=>lien.html
    [2]=> array
    [0]=>azerty
    [1]=>niark
    [2]=> azerty
    donc dans la case 0 on a toujours TOUTES les "réponses" motifs généraux capturés (donc trois vu qu'on en a trois qui correspondent)
    dans la case 1 on a toujours TOUS les liens capturés (donc trois vu qu'on a capturé trois "réponses" au motif)
    dans la case 2 on a toujours TOUT ce qui est capturé dans le deuxième lien

    le problème comme tu peux le voir c'est que tu captures des choses en trop dans la case [0][2] de ton tableau. il faut donc soit améliorer ton motif soit je me trompe avec le preg_match_all et je te dis une grosse connerie auquel cas, mea culpa

    voilà dites-moi pour les bêtises et si ce n'est pas ce que tu voulais, expose un peu mieux ton problème comme le suggérait eyquem

  9. #9
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Je comprends les choses comme toi, Miaou.

    J’apporterais deux précisions:

    - la description de preg_match_all() fait état d’un drapeau facultatif:

    preg_match_all ( $pattern , $subject , $matches [, $flags [, $offset ]] )
    Quand $flags n’est pas spécifié, il est automatiquement fixé à la valeur par défaut PREG_PATTERN_ORDER


    - PREG_PATTERN_ORDER détermine que
    l’élément 0 de $matches est un tableau de tous les matches totaux
    l’élément 1 de $matches et un tableau de tous les 1ers groupes
    l’élément 2 de $matches est un tableau de tous les 2ièmes groupes
    etc
    le dernier élément de $matches contient tous les (n+1)ièmes (=derniers) groupes du pattern.
    n étant le nombre de groupes dans le pattern





    Pour ma part , reprenant l’exemple que tu as pris, Miaou:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <a href="www.nasa.gov"> dsqcoucou
    dsq</a>Challenger
    <a href=...
    <a href="www.hominides.com">coucou</a>niark<a href=...
    <a href="www.pacifique.ch">plop</a>honohuhu<a href=...
    <a href="www.evene.fr">coucou</a>
    cyrano<a href=...
    J’écrirais le résultat plutôt ainsi

    Code : 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
    [0]=> array 
    
        [0]=><a href="www.nasa.gov"> dsqcoucou\ndsq</a>Challenger\n<a href=
        [1]=><a href="www.hominides.com">coucou</a>niark<a href=
        [2]=><a href="www.pacifique.ch">plop</a>honohuhu<a href=...\n<a href="www.evene.fr">coucou</a>\ncyrano<a href=
    
    [1]=> array
    
        [0]=>www.nasa.gov
        [1]=>www.hominides.com
        [2]=>www.pacifique.ch
    
    [2]=> array
    
        [0]=>Challenger
        [1]=>niark
        [2]=>cyrano


    ------------------------------------------------------



    le problème comme tu peux le voir c'est que tu captures des choses en trop dans la case [0][2] de ton tableau.
    Mais trop par rapport à quel objectif ?
    Seul piero53 peut dire en quoi cela ne lui convient pas d’avoir $desc[0][2] valant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <a href="www.pacifique.ch">plop</a>honohuhu<a href=... \n<a href="www.evene.fr">coucou</a>\ncyrano<a href=
    car pour ce qui est de ce qu’il cherche à capter, il peut les obtenir par $desc[2] :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $desc[2][0]=>Challenger
    $desc[2][1]=>niark
    $desc[2][2]=>cyrano



    --------------------------------------------------------



    Ce qui peut par contre être considéré comme gênant, je pense,
    avec la RE proposée par piero53 dans le message #7 , à savoir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '#<a href="([^"]+)">.*coucou.*</a>(.+)<a href=#Uis'
    est que les [1][i] et les [2][i] ne se correspondent pas selon les correspondances existant dans le texte.
    [1][i] est le lien capturé dans le premier groupe, et [2][i] est le texte apres </a> capturé dans le second groupe


    Pour obtenir les bonnes correspondances, il faut arriver à trouver une RE du genre

    '#<a href="(.+?)">.*?coucou.*?</a>(.+?)<a href=#’
    mais dans laquelle les caractères .*? qui précèdent coucou ne doivent pas contenir ’</a>’.


    Il ya deux possibilités


    1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '#<a href="([^"]+?)">((?!</a>).)*?coucou.*?</a>(.+?)(?=<a href=)#'

    Dans cette RE, je n’ai pas mis U, les ? ont donc pour effet de limiter la gloutonnerie des quantificateurs,
    comme cela existe en PHP aussi:
    http://fr2.php.net/manual/fr/regexp....repetition.php

    Cette RE ne me plait pas à caude de la partie ((?!</a>).)*? qui ne me semble pas naturelle dans une RE.
    Il est préférable de fournir au moteur de regex un motif à chercher qui va lui permettre de matcher progressivement sur ce qu’il rencontre au lieu de compter sur sa capacité à revenir en arrière plusieurs fois pour faire des essais de manières différentes.


    2)
    L'autre motif est le suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '#(?:(?:<a href="[^“]+">.+?</a>.+?(?=<a href=))+)?<a href="([^“]+)">.*?coucou.*?</a>(.+?)(?=<a href=)#s'
    EDIT 4 mars 10
    Cette RE ne marche pas correctement. Cf le post #11 qui suit dans cette file.


    On fait matcher autant de fois que possibles avec
    '(??:<a href="[^“]+">.+?</a>.+?(?=<a href=))+)?'
    et on oblige
    '<a href="([^“]+)">.*?coucou.*?</a>(.+?)(?=<a href=)’ à matcher obligatoirement en dernier avec la première séquence contenant ’coucou’ rencontrée, ce qui rend ’coucou’ nécessairement absent de la portion répétitive précédente.







    En utilisant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match_all('#(?:(?:<a href="[^“]+">.+?</a>.+?(?=<a href=))+)?<a href="([^“]+)">.*?coucou.*?</a>(.+?)(?=<a href=)#s', $text, $desc, PREG_SET_ORDER)
    on devrait obtenir, s’il n’y a pas d’erreur,
    EDIT 4 mars 10
    Eh bien si, il y a une erreur. Cette RE n'est pas suffisamment correcte. Cf le message #11 qui suit.

    un tableau $desc dont les éléments sont les matches successivement rencontrés dans la chaîne,
    parce qu'il y a le drapeau PREG_SET_ORDER dans cette instruction.

    Chaque $desc[i] contient les deux groupes du match: le lien présent dans <a href="([^“]+)"> dans $desc[i][0] , et la séquence située dans </a>(.+?)(?=<a href=) juste après, dans $desc[i][1]







    Nota bene:

    piero53, le problème de ta RE se terminant par ’<a href=’ est que si un matche déborde sur la séquence suivante commençant par ’<a href=’, cette séquence ne peut pas être captée comme match: la regex loupe alors certaines séquences que l’on souhaiterais pourtant attraper. En effet, les matches que détectent les regex ne se recouvrent pas les uns les autres.

  10. #10
    Membre régulier
    Inscrit en
    Décembre 2008
    Messages
    483
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 483
    Points : 105
    Points
    105
    Par défaut
    merci pour ces réponses

    je comprend maintenant mieux le fonctionnement de preg_match

  11. #11
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Je me suis rapidement aperçu que ma RE numero 1) ne marche pas comme je souhaitais.
    Je ne l'avais pas testée sur une chaîne suffisamment complexe.



    Elle marche bien sûr quand il y a un seul match possible dans la chaîne explorée, mais le problème est que lorsqu’il y a plusieurs matches possibles, toutes les chaînes qui doivent matcher ne sont pas détectées mais seulement la dernière:

    Code : 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
    import re
     
    ch = '''adele <a href="www.iana.org"> cuicui semelle</a> azerty
    <a href="www.jackson.five"> saucisson bateau</a>
    <a href="www.lelutin.com">coucou hibou</a>Il fait hou hou,hou hou <---
    <a href="www.france-pluie.fr/">cerf-volant</a> blanchiment
    <a href="www.clown.fr">glacis amaranthe</a> morsure
    <a href="www.larousse.fr">le coucou migrateur</a>passereau <----------
    <a href="www.ancestry.com">Andromede</a>ministere
    <a href="www.laprovence.com">pollution</a>polychlorobiphényles
    <a href="www.oiseaux.net">le malin coucou wiwi</a>canopee <-----------
    <a href="www.lapendule.com">vente de coucous online</a>Rouen <--------
    <a href="www.cetou.com">sardine</a>huile d'olive'''
     
    pat = re.compile('(?:(?:<a href="[^"]+">.+?</a>.+?(?=<a href=))+)?'\
                     +'<a href="([^"]+)">.*?coucou.*?</a>(.+?)(?=<a href=)'
                     ,re.DOTALL)
     
    for i,mm in enumerate(pat.finditer(ch)):
        print '\n\nMatch mm numero '+str(i)
        print '---mm.group()\n"""'+mm.group()+'"""'
        print '===mm.groups()\n',mm.groups()

    Match mm numero 0
    ---mm.group()
    """<a href="www.iana.org"> cuicui semelle</a> azerty
    <a href="www.jackson.five"> saucisson bateau</a>
    <a href="www.lelutin.com">coucou hibou</a>Il fait hou hou,hou hou <---
    <a href="www.france-pluie.fr/">cerf-volant</a> blanchiment
    <a href="www.clown.fr">glacis amaranthe</a> morsure
    <a href="www.larousse.fr">le coucou migrateur</a>passereau <----------
    <a href="www.ancestry.com">Andromede</a>ministere
    <a href="www.laprovence.com">pollution</a>polychlorobiphényles
    <a href="www.oiseaux.net">le malin coucou wiwi</a>canopee <-----------
    <a href="www.lapendule.com">vente de coucous online</a>Rouen <--------
    """
    ===mm.groups()
    ('www.lapendule.com', 'Rouen <--------\n')


    Certes le lien 'www.lapendule.com' et la chaîne 'Rouen <----------\n' sont bien les deux éléments qui doivent être trouvés ensemble.

    Mais il manque la capture de

    www.lelutin.com’, ’Il fait hou hou,hou hou <---’

    www.larousse.fr’ <http://www.larousse.fr’/>, 'passereau <----------’

    www.oiseaux.net’, 'canopee <-----------’





    J'ai essayé des quantités de modifications pour parvenir à ce que je souhaitais, changer des + en *, mettre une assertion conditionnelle alambiquée, des répétitions de portions qui s'emboitaient, des contorsions.... rien ne marche parce qu'il y a trop de morceaux .+? ou .*? à placer entre des points fixes trop peu nombreux.



    Ce que je voulais, c'est ce que j'ai écrit dans le précédent post, une RE
    '#<a href="(.+?)">.*?coucou.*?</a>(.+?)<a href=#’
    dans laquelle les caractères .*? qui précèdent coucou ne contiennent pas ’</a>’,
    tout en n'étant pas la deuxième RE donnée dans 2).

    Mon idée était de pouvoir obtenir les matches sur des lignes du genre
    <a href="tous-les-fruits.com">citron-->> Sicile coucou</a>exportation
    ou
    <a href="tous-les-fruits.com">citron/orange coucou</a>exportation
    c'est à dire des lignes dans lesquelles il n'y ait pas '</a>' en amont de 'coucou' mais dans lesquelles puissent se trouver un ou plusieurs caractères de la chaîne '</a>'.
    On peut en effet arriver à une RE en mettant [^<]*? à certains endroits, ce qui empêche de détecter des lignes dans lesquelles se trouverait ce signe. Et idem avec '>' ou '/'. Alors comment faire pour éviter cela ? Petit défi sans grande portée peut être, mais c'est pour le fun.

    ----------------------------------------

    Le problème c'est que je n'y suis pas arrivé et je ne vois pas comment on peut y arriver. Je baisse donc les bras.

    Pour obtenir le résultat voulu, il n'y a que la RE 2) , bien que le morceau de RE ((?!</a>).)*? ne me plaise pas.
    Je pensais bien que personne ne s'apercevrait que l'autre est déficiente parce que celle ci est plus courte, moins compliquée. Je vais donc m'en contenter aussi puisqu'elle marche bien.


    Code : 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
    import re
     
    ch = '''adele <a href="www.iana.org"> cuicui semelle</a> azerty
    <a href="www.jackson.five"> saucisson bateau</a>
    <a href="www.lelutin.com">coucou hibou</a>Il fait hou hou,hou hou <---
    <a href="www.france-pluie.fr/">cerf-volant</a> blanchiment
    <a href="www.clown.fr">glacis amaranthe</a> morsure
    <a href="www.larousse.fr">le coucou migrateur</a>passereau <----------
    <a href="www.ancestry.com">Andromede</a>ministere
    <a href="www.laprovence.com">pollution</a>polychlorobiphényles
    <a href="www.oiseaux.net">le malin coucou wiwi</a>canopee <-----------
    <a href="www.lapendule.com">vente de coucous online</a>Rouen <--------
    <a href="www.cetou.com">sardine</a>huile d'olive'''
     
    pat = re.compile('<a href="([^"]+?)">((?!</a>).)*?coucou.*?</a>(.+?)(?=<a href=)'
                     ,re.DOTALL)
     
    for i,mm in enumerate(pat.finditer(ch)):
        print '\n\n----------------------------------------------------------------------'
        print 'Match mm numero '+str(i)
        print '     mm.group()\n"""'+mm.group()+'"""'
        print '     mm.groups()\n',mm.groups()

    Code : 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
    29
    30
    31
    32
    33
    34
    35
     
    ----------------------------------------------------------------------
    Match mm numero 0
         mm.group()
    """<a href="www.lelutin.com">coucou hibou</a>Il fait hou hou,hou hou <---
    """
         mm.groups()
    ('www.lelutin.com', '', 'Il fait hou hou,hou hou <---\n')
     
     
    ----------------------------------------------------------------------
    Match mm numero 1
         mm.group()
    """<a href="www.larousse.fr">le coucou migrateur</a>passereau <----------
    """
         mm.groups()
    ('www.larousse.fr', ' ', 'passereau <----------\n')
     
     
    ----------------------------------------------------------------------
    Match mm numero 2
         mm.group()
    """<a href="www.oiseaux.net">le malin coucou wiwi</a>canopee <-----------
    """
         mm.groups()
    ('www.oiseaux.net', ' ', 'canopee <-----------\n')
     
     
    ----------------------------------------------------------------------
    Match mm numero 3
         mm.group()
    """<a href="www.lapendule.com">vente de coucous online</a>Rouen <--------
    """
         mm.groups()
    ('www.lapendule.com', ' ', 'Rouen <--------\n')

  12. #12
    Membre régulier
    Inscrit en
    Décembre 2008
    Messages
    483
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 483
    Points : 105
    Points
    105
    Par défaut
    edit : résolu

  13. #13
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    piero53, tu demandais, avant édition de ton message, comment ajouter la condition que se trouve le mot "salut" dans le lien capturé, outre le fait que doive se trouver le mot "coucou" avant '</a>'.

    Mon souci étant en outre depuis le message #9 d'arriver à trouver une RE qui fasse ce qu'on lui demande tout en assurant une correspondance correcte entre le lien trouvé et la terminaison recherchée.





    Face à cette nouvelle question je dirais qu'il ne faut pas vouloir tout faire avec seulement une regex, et particulierement des trucs tordus.

    Je ne sais pas quelle manie vous avez en PHP de vouoir trouver par regex des chaînes dans lesquelles IL NE DOIT PAS Y AVOIR tel ou tel mot.

    Les regex sont faites pour trouver des motifs, pas pour trouver des non-motifs.
    Les assertions négatives avant/arrière ne sont, me semble-t-il, destinées qu'à indiquer des absences de motif en avant ou en arrière d'UNE position dans la chaîne explorée, pas sur des PLAGES de positions.




    Si tu y tiens tu peux utiliser la RE tarabiscotée suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '#<a href="((?:(?!salut)[^"])+)">((?!</a>).)*coucou.*</a>(.+)(?=<a href=)#Us'
    Ça ne fera rien que deux motifs à assertion négative courante......




    Mais je juge ça comme étant un crabe à tête de poulet.

    J'estime que quand on veut exclure ou vérifier l'absence d'une sous-chaîne dans une chaîne, il faut recourir à une méthode de chaîne, c'est fait pour ça, et non pas à un vaisseau spatial pour traverser la rue.

    En Python, il y a une fonction re.findall() qui fait la même chose que preg_match_all()
    mais il y a aussi une fonction re.finditer() que j'ai déjà utilisée dans mon précédent post pour vérifier ma RE en Python. Cette fonction renvoie un itérateur. Ce dernier débite les matches les uns après les autres à volonté. Cela veut dire qu'on peut obtenir les matches par une instruction next() ou bien par une boucle for.

    Dans une telle boucle il suffit de faire un test sur les chaînes que sont les groupes d'un match, on peut même se payer le luxe d'une recherche à plusieurs tests tels que les suivants et de modifier les captures avant enregistrement:

    - présence du mot 'coucou' après l'adresse et avant '</a>'

    - obligatoirement 'www' dans le lien

    - pas de mot 'pluie' dans le lien

    - s'il y a 'http://' dans l'adresse il faut l'éliminer mais garder le lien

    - on met tout ce qui est capté après le '</a>' entre 2 fois '##'


    Code : 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
    29
    30
    import re
     
    ch = '''adele <a href="www.iana.org"> cuicui semelle</a> azerty
    <a href="www.jackson.five"> saucisson bateau</a>
    <a href="www.lelutin.com">coucou hibou</a>Il fait hou hou,hou hou <---
    <a href="www.france-pluie.fr/">cerf-volant</a> blanchiment
    <a href="www.clown.fr">glacis amaranthe</a> morsure de coucou <///////
    <a href="www.larousse.fr">le coucou migrateur</a>passereau <----------
    <a href="nhc.noaa.gov/">prepared coucou</a>typhoon <------------------
    <a href="www.ancestry.com">Andromede</a>ministere
    <a href="www.laprovence.com">pollution</a>polychlorobiphényles
    <a href="http://www.oiseaux.net">le malin coucou wiwi</a>canopee <----
    <a href="www.lapendule.com">vente de coucous online</a>Rouen <--------
    <a href="www.cetou.com">sardine</a>huile d'olive'''
     
    pat = re.compile('<a href="([^"]+)">(?:(?!</a>).)*?coucou.*?</a>(.+?)(?=<a href=)'
                     ,re.DOTALL)
     
    liste = []
    for i,mm in enumerate(pat.finditer(ch)):
        print '\n\n----------------------------------------------------------------------'
        print 'Match mm numero '+str(i)
        print '     mm.group()\n"""'+mm.group()+'"""'
        lien,termin = mm.groups()
        print '     mm.groups()\n',lien,termin
        if 'www' in lien and 'pluie' not in lien:
            liste.append((lien.replace('http://',''),'##'+termin+'##'))
     
    for x in liste:
        print x

    Le resultat est
    Code : 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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    ----------------------------------------------------------------------
    Match mm numero 0
         mm.group()
    """<a href="www.lelutin.com">coucou hibou</a>Il fait hou hou,hou hou <---
    """
         mm.groups()
    www.lelutin.com Il fait hou hou,hou hou <---
     
     
     
    ----------------------------------------------------------------------
    Match mm numero 1
         mm.group()
    """<a href="www.larousse.fr">le coucou migrateur</a>passereau <----------
    """
         mm.groups()
    www.larousse.fr passereau <----------
     
     
     
    ----------------------------------------------------------------------
    Match mm numero 2
         mm.group()
    """<a href="nhc.noaa.gov/">prepared coucou</a>typhoon <------------------
    """
         mm.groups()
    nhc.noaa.gov/ typhoon <------------------
     
     
     
    ----------------------------------------------------------------------
    Match mm numero 3
         mm.group()
    """<a href="http://www.oiseaux.net">le malin coucou wiwi</a>canopee <----
    """
         mm.groups()
    http://www.oiseaux.net canopee <----
     
     
     
    ----------------------------------------------------------------------
    Match mm numero 4
         mm.group()
    """<a href="www.lapendule.com">vente de coucous online</a>Rouen <--------
    """
         mm.groups()
    www.lapendule.com Rouen <--------
     
    ('www.lelutin.com', '##Il fait hou hou,hou hou <---\n##')
    ('www.larousse.fr', '##passereau <----------\n##')
    ('www.oiseaux.net', '##canopee <----\n##')
    ('www.lapendule.com', '##Rouen <--------\n##')
    >>>

    Comment voulez vous faire la même chose avec seulement une regex qui ferait tout ?

    En l'occurence, l'usage d'un itérateur est plus pratique qu'une fonction preg_match() car on crée directement la liste finale, on n'a pas besoin d'enregistrer d'abord tous les résultats dans une liste avec preg_match() puis de reprendre cette liste et de l'expurger et faire les modifications voulues sur ses éléments.



    On peut même utiliser une list comprehension pour condenser le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    pat = re.compile('<a href="([^"]+)">(?:(?!</a>).)*?coucou.*?</a>(.+?)(?=<a href=)'
                     ,re.DOTALL)
     
    liste = [ (mm.group(1).replace('http://',''),'##'+mm.group(2)+'##')
               for mm in pat.finditer(ch)
               if 'www' in mm.group(1) and 'pluie' not in mm.group(2) ]
     
    for x in liste:
        print x



    PS
    une question que je me pose est: peut on faire en PHP quelque chose de similaire au code ci-dessus utilisant un itérateur ?
    Ou bien est on obligé de créer d'abord une liste en mémoire de toutes les occurences avant de les traiter ?

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

Discussions similaires

  1. [TP7] Liens pour tuto de programmation de jeux
    Par doderic dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 22/02/2005, 21h00
  2. Lien pour TELECHARGER une image plutôt que pour l'ouvrir
    Par nabab dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 17/01/2005, 18h07
  3. lien pour télécharger
    Par Kaimann dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 13/10/2004, 12h05
  4. [ STRUTS ][ JSP ][ ArrayList] un lien pour trier
    Par LoulouFifi dans le forum Servlets/JSP
    Réponses: 7
    Dernier message: 03/02/2004, 17h24
  5. Tutoriels et liens pour le Borland Database Engine
    Par Community Management dans le forum Paradox
    Réponses: 0
    Dernier message: 25/03/2002, 10h23

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