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 pour détecter URL non incluse dans BBCODE [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 44
    Points : 46
    Points
    46
    Par défaut Regex pour détecter URL non incluse dans BBCODE
    Bonjour.

    Mon besoin est d'extraire les URL d'un texte qui ne soient pas contenues dans un BBCODE, donc sont concernées les balises URL(avec ou sans paramètre =) et IMG.

    La regex suivante présente deux dysfonctionnements que j'ai du mal à saisir. (elle ne traite que le cas des balises URL, pas les IMG)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /(?:(?<!(\[\/url\]|\[\/url=))(\s|^))((https?|ftps?|ircs?|http?|ftp?|irc?):\/\/\S+)(?:(?<![[:punct:]])(\s|\.?$))/igm
    Dans la deuxième capture, le but de la recherche est de récupérer un chaîne débutant par un nom de protocole, suivis de :// et un nombre de caractères indéterminé jusqu'à tomber sur un espace ou fin de ligne.


    1er dysfonctionnement :
    Les URL se terminant par / ou un = (cas d'une url se terminant par variable non affectée ; si la variable est affectée d'une valeur, la regexfonctionne ) ne sont pas prises en compte.
    Exemple :
    http://www.machin.com/
    http://www.machin.com/page.php?id=



    2e dysfonctionnement :

    Seuls les liens dans les balises URL devraient être ignorés.
    Il se trouve que celles incluses dans les balises IMG le sont aussi (ce que je cherchais à faire au final, exclure à la fois les balises URL et IMG, mais dans le cas présent, seule la balise URL est indiquée dans le "negative groupbehind".


    Pouvez-vous m'expliquer l'erreur ?

    D'avance, merci.

  2. #2
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Ça marche pô 1: le slash et le égal font partis de la class [[:punct:]] donc la condition (?<![[:punct:]]) interdit toutes les urls se terminant ces caractères.

    Ça marche pô 2: Ton lookbehind (?<!(\[\/url\]|\[\/url=)) n'est en fait pas très utile car il est suivit de quelque chose de bien plus contraignant: (\s|^). Or je doute qu'il y est un quelconque espace entre une balise [url] ou [img]et l'adresse.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 44
    Points : 46
    Points
    46
    Par défaut
    Bonjour.

    Merci pour cette analyse.

    Concernant le point 1, effectivement, le problème vient bien de là. Je n'avais pas fait attention à ce qu'englobait punct comme liste de caractères, et ne pensais pas / et = comme des caractères de ponctuation..
    Le point 1 est résolu.

    Concernant le point 2, je suppose éliminer des espaces insérés entre la balise fermante ou après le =. (c'est une regex trouvée sur le net)
    D'ailleurs cela ne semble pas fonctionner car si j'insère un espace ou retour chariot (regex exécutée avec option multilines) entre une fin de balise url et le début de l'url, l'url incluse n'est pas ignorée.

    Si j'ôte (\s|^), cela marche encore moins, seules les url contenues non conformes au format indiqué (soit commençant directement par www. sans http:// ou bien une erreur dans l'url ttp://www.machin.com/) sont ignorées.

  4. #4
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Tu devrais poster une chaîne d'exemple avec plusieurs cas de figure problématiques, ça permettra de voir quel syntaxe de bbcode tu utilises. Sinon de but en blanc, je pondrai quelque chose comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $pattern='~
    (?=[fhi[]) # pour aller rapidement au positions intéressantes sans tester toute la pattern
    (?: \[
        (?: img]    [^[]*+ (?:\[(?!/img])[^[]*)*+ \[/img]
          | url[]=] [^[]*+ (?:\[(?!/url])[^[]*)*+ \[/url]
        ) (*SKIP) (*F) # <- F force la pattern à échouer
      | # ^ en cas d\'echec le moteur reprend à la position du skip (et donc saute
        # les parties inutiles déjà parcourues)
        (?<![^\s]) # <-------------
        (?:http|ftp|irc)s?://\S+
        (?<![^?&#/\PP]) # <--------- avec une double négation, tu peux facilement ajouter des exceptions
        (?![^\s.]) # <-------------
    )
    ~xi';
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 44
    Points : 46
    Points
    46
    Par défaut
    Merci.

    Une fois le point 1 corrigé de la regex initiale, cela correspond parfaitement à ce que j'attendais (sauf le cas où la balise n'est pas délimitée par des espaces, par exemple entre deux parenthèses), mais je ne comprends pas pourquoi cela fonctionne alors que seule la balise url est indiquée et pas la balise img.
    Tel demandé, un jeu de test en pièce-jointe.


    La nouvelle regex proposée fonctionne parfaitement, (seul le cas aussi indiqué ci-dessus, soit la ligne 7 du fichier de test, n'est pas pris en compte).
    Je n'ai que quelques notions de regex et ne les ai jamais réellement pratiquées, juste récupéré quelques unes ci et là pour des besoins très ponctuels.
    J'ai néanmoins compris l'ensemble de ce qui est proposé (merci pour les commentaires), sauf ce qui était visé par la ligne 2 (?=[fhi[]).
    Si j'ai bien compris, c'est un positive lookahead sur un jeu de caractères

    Le but étant avant tout d'apprendre, pas faire du simple copier/coller...

    Merci.
    Fichiers attachés Fichiers attachés

  6. #6
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    je ne comprends pas pourquoi cela fonctionne alors que seule la balise url est indiquée et pas la balise img
    Car dans ta pattern ce n'est pas la condition (?<!(\[\/url\]|\[\/url=)) qui intervient (elle ne sert d'ailleurs à rien), c'est uniquement le fait d'imposer un espace avant l'url avec (\s|^) qui va exclure d'emblée les sous-chaînes:
    Code txt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [url=http://...
    [url]http://...
    [img=http://...
    [img]http://...
    car dans aucune d'elles cet espace n'est présent. Et c'est pour cette même raison qu'une url entre parenthèses ne matchera pas.

    En ce qui concerne (?=[fhi[]), c'est une astuce pour accélérer la recherche lorsqu'une pattern comporte plusieurs branches. Disons qu'on a une pattern avec branches: Axxxxx|Bxxxxx|Cxxxxxx|Dxxxxx où les xxxx peuvent être n'importe quoi. À chaque position de la chaîne, le moteur de regex va devoir dans le pire des cas (quand à cette position il n'y a ni A, ni B, ni C, ni D) tester les 4 branches avant d'échouer et d'essayer la position suivante. Mais si je change la pattern en (?=[ABCD])(?:Axxxxx|Bxxxxx|Cxxxxxx|Dxxxxx), plus besoin de tester les 4 branches à chaque position ne commençant ni par A,B,C ou D. Grâce à (?=[ABCD]), j'aurai précipité l'échec de la pattern. Cette technique s'appelle la discrimination par le premier caractère.

    Pour ce qui est du cas de l'url entre parenthèses, il suffit d'ajouter les parenthèses dans les lookarounds autour de l'url.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 44
    Points : 46
    Points
    46
    Par défaut
    Merci pour ces explications qui vont m'inciter à prendre le temps d'apprendre tout cela.

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

Discussions similaires

  1. Afficher une image d'un dossier non inclus dans Apache
    Par Thordax dans le forum Langage
    Réponses: 1
    Dernier message: 07/06/2010, 21h38
  2. HtmlUnit : remplir des champs non inclus dans un formulaire
    Par lahmar.abdel1 dans le forum Général Java
    Réponses: 0
    Dernier message: 12/05/2009, 11h31
  3. Réponses: 3
    Dernier message: 23/12/2008, 22h34
  4. Réponses: 1
    Dernier message: 03/03/2007, 12h28
  5. Redirection URL Non visible dans la barre d'adresse
    Par domileg dans le forum Langage
    Réponses: 5
    Dernier message: 04/08/2006, 09h02

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