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 URL: interdire balise html ?


Sujet :

Langage PHP

  1. #1
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    317
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 317
    Points : 135
    Points
    135
    Par défaut Regex URL: interdire balise html ?
    Bonjour à tous,

    voila, j'ai fait un petite regex pour repéré des urls dans un texte, mais après quelques petit test, jais repéré un petit soucis:
    j'aimerai pouvoir supprimer les balises html, qui ne font pas partie de l'url xD
    Voici tout d'abbord la regex:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $protocole  = "(https?|ftp|gopher|telnet|file|notes|ms-help)";
    $www        = "(www.)?";
    $domaine    = "(\w.-)+";
    $ext        = "([\w.]{3,8})+";
    $ports      = "(:[\d]{2,5})?";
    $add        = "(/([\w:#@&%/;$~_?\+-.]+))";
    $url        = "((".$protocole."://".$www."".$domaine."".$ext."".$ports."".$add."))";
     
    $string     = preg_replace($url, '<a href="$1">$1</a>');

    donc je m'explique:

    une url de type
    http://monsite.soudomaine.com/page/test.php?page=<script>blabla</script>
    devrai passée (même si cette url est embétante, c'est le seul exemple que j'ai trouvé comme ça ^^)
    par contre, imaginons un bout de texte:
    <b>je vous conseil d'allé voir a l'url: http://monsite.soudomaine.com/page/test.php</b>
    et bien l'url repérée est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    http://monsite.soudomaine.com/page/test.php</b>
    avec le </b> a la fin, qui pause problème.

    Si vous avez des idées de solution, je prends avec plaisir
    Tout autre conseil pour améliorer cette regex est également le bienvenue.

    Merci =)

  2. #2
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Salut,

    Je ne sais pas si j'ai bien compris la problématique, mais j'ai un peu joué avec tes exemples pour arriver à ç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
    15
    16
    17
    18
    19
    20
    21
    <?php
    $str = "<b>je vous conseille d'allé voir a l'url: http://monsite.soudomaine.com/page/test.php</b>";
    $str = "http://monsite.soudomaine.com/page/test.php?page=<script>blabla</script>";
     
    $protocole  = "(?:https?|ftp|gopher|telnet|file|notes|ms-help)";
    $www        = "(?:www.)?";
    $domaine    = "(?:(?:(?:[\w-]+)\.)+)";
    $ext        = "(?:[\w.]{3,8})+";
    $ports      = "(?::[\d]{2,5})?";
    $add        = "(?:/([\w:#@&%/;$~_?\+-.]+))=?";
     
    $reg        = "! $protocole://$www $domaine $ext $ports $add !x";
     
    preg_match($reg, $str, $m);
    print_r($m);
    print("\n");
     
    $str = preg_replace($reg, '<a href="$1">$1</a>', $str);
    print_r($str);
     
    exit();
    Si ça peut aider...

  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
    Je pene qu’il suffit d’ajouter (?<!</b>) à la fin de $add

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $add        = "(/([\w:#@&%/;$~_?\+-.]+(?<!</b>)))";
    Pour que le moteur de regex s’arrête au premier </b>, il faut mettre aussi un ? après le quantificateur +, je pense:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $add        = "(/([\w:#@&%/;$~_?\+-.]+?(?<!</b>)))";
    (?<!</b>) a beau être de longueur zéro, le moteur de regex teste néamoins sa présence à chaque avancée de un caractère qu’il fait, comme pour tout autre motif de longueur non zéro.

    Je crois bien que c’est c’est comme ça que ça se passe, j’espère que je ne me trompe pas sur leprincipe.

    Mais comme je ne connais pas bien PHP, j’espère que je l’ai bien positionné aussi. Si ça ne marche pas essayer de bouger sa place par rapport aux parenthèses, dont je ne perçois pas bien la justification.

  4. #4
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    317
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 317
    Points : 135
    Points
    135
    Par défaut
    Merci.

    Je me bas encore avec ces deux exemples:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <p>blabla</p>
    <p>http://www.unsite.com/forum-83-277379-p1-couper-mot-trop-long-sans-couper-url.html</p>
    <p>blabla</p>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <p>blabla</p>
    <p>http://www.unsite.com/forum-83-277379-p1-couper-mot-trop-long-sans-couper-url.html </p>
    <p>blabla</p>
    Résultat attendu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <p>blabla</p>
    <p><a href="URL COMPLETE">www.unsite.com/forum...url.html</a></p>
    <p>blabla</p>
    pour le premier exemple, j'y arrive avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            $protocole  = "(https?|ftp|gopher|telnet|file|notes|ms-help)";
            $www        = "(www.)?"; //3
            $domaine    = "([\w]+)"; //4
            $ext        = "([\w.]{3,8})+"; //5
            $ports      = "(:[\d]{2,5})?"; //6
            $add1       = "(/[\w:#@&%=/;$~_?\+-.]{5})?"; //7
            $add2       = "([\w:#@&%=/;$~_?\+-.]+)"; //8
            $add3       = "(([\w:#@&%=/;$~_?\+-.]){15}){1}"; //9
            $balise     = "(&lt;){1}"; //10
            $url        = "((".$protocole."://".$www."".$domaine."".$ext."".$ports."".$add1."".$add2."".$add3.")".$balise.")";
     
            $string     = preg_replace($url, '<br><br><a href="$1">$3$4$5$6$7...$9</a><br><br>&lt;', $string);
    par contre elle passe a coté de la seconde, puisqu'elle cherche forcement une balise a la fin de l'url

    et pour la seconde, j'y arrive avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            $protocole  = "(https?|ftp|gopher|telnet|file|notes|ms-help)";
            $www        = "(www.)?"; //3
            $domaine    = "([\w]+)"; //4
            $ext        = "([\w.]{3,8})+"; //5
            $ports      = "(:[\d]{2,5})?"; //6
            $add1       = "(/[\w:#@&%=/;$~_?\+-.]{5})?"; //7
            $add2       = "([\w:#@&%=/;$~_?\+-.]+)"; //8
            $add3       = "(([\w:#@&%=/;$~_?\+-.]){15}){1}"; //9
            $balise     = "[\s]{1}"; //10
            $url        = "((".$protocole."://".$www."".$domaine."".$ext."".$ports."".$add1."".$add2."".$add3.")".$balise.")";
     
            $string     = preg_replace($url, '<br><br><a href="$1">$3$4$5$6$7...$9</a><br><br>&lt;', $string);
    mais la première url est détéctée avec le </p> a la fin

    Quelques explications:
    - la différence entre les deux url, c'est l'espace avant la balise fermante </p>
    - ça doit marché pour <p><b><u><i>
    - il n'y a pas forcement de balise.
    - il faut que $add3 retourne un bout de la fin de l'url

    Dois-je passé l'une puis l'autre après ou y'il un moyen pour n'en faire qu'une ?
    Merci encore

  5. #5
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    317
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 317
    Points : 135
    Points
    135
    Par défaut
    Mouarf, c'est bon!
    Le problème venait du fait que je passais un htmlentities avant la fonction.

    là tout fonctionne nikel:

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <p>
    	http://www.unsite.com/forum-83-277379-p1-couper-mot-trop-long-sans-couper-url.html</p>
    <p>
    	test</p>
    <p>
    <p>
    	http://www.unsite.com/forum-83-277379-p1-couper-mot-trop-long-sans-couper-url.html </p>
    Fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    $protocole  = "(https?|ftp|gopher|telnet|file|notes|ms-help)";
    $www        = "(www.)?"; //3
    $domaine    = "([\w]+)"; //4
    $ext        = "([\w.]{3,8})+"; //5
    $ports      = "(:[\d]{2,5})?"; //6
    $add1       = "(/[\w:#@&%=/;$~_?\+-.]{5})?"; //7
    $add2       = "([\w:#@&%=/;$~_?\+-.]+)"; //8
    $add3       = "(([\w:#@&%=/;$~_?\+-.]){15}){1}"; //9
    $balise     = "(?<!</p>)"; //10
    $url        = "((".$protocole."://".$www."".$domaine."".$ext."".$ports."".$add1."".$add2."".$add3."".$balise."))";
     
    $string     = preg_replace($url, '<a href="$1">$3$4$5$6$7...$9</a>', $string);
    Résultat
    soit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <p>
    	<a href="http://www.unsite.com/forum-83-277379-p1-couper-mot-trop-long-sans-couper-url.html">www.unsite.com/forum...couper-url.html</a></p>
    <p>
    	test</p>
    <p>
    </p><p>
    	<a href="http://www.unsite.com/forum-83-277379-p1-couper-mot-trop-long-sans-couper-url.html">www.unsite.com/forum...couper-url.html</a> </p>

    Merci encore
    ++

  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
    Bonjour,


    D’une part, je trouve la RE très vasouillarde.


    (([\w:#@&%=/;$~_?\+-.]){15}){1}
    Qu’est ce que c’est ce machin ?

    [\w:#@&%=/;$~_?\+-.] représente un ensemble de caractères possible pour UNE position
    Entouré de parenthèses, cela permet de capturer le dernier caractère matché par ce symbole (c’est un symbole constitué de plusieurs caractères, mais il faut le voir comme UN symbole)
    Dans la suite, j’abrège [\w:#@&%=/;$~_?\+-.] par [./.] , avec / gardé en évidence

    {15} signifie qu’il faut trouver 15 caractères autorisés par ce symbole, sur 15 positions d’affilée
    À nouveau, des parenthèses permettent de capturer ce motif de 15 caractères

    Et ensuite le {1} dit qu’il faut un et un seul tel motif de 15 caractères
    Mais le {15} disait déjà qu’il faut trouver ces 15 caractères.
    Le {1} ne sert donc à rien.






    Le groupe //3 est défini dans la ligne
    $protocole = "(https?|ftp|gopher|telnet|file|notes|ms-help)";
    pas dans la suivante.
    Il s’ensuit que la ligne
    $add3 = "(([\w:#@&%=/;$~_?\+-.]){15}){1}";
    définit le groupe 10,
    et aussi un groupe 11 puisqu’il y a 2 parenthèses ouvrantes dans cette ligne.






    Il y a donc dans ta RE une succession de lignes qui reviennent à ceci:
    (/[./.]{5})?
    ([./.]+)
    (([./.]){15})


    Si le caractère / ne faisait pas partie des caractères autorisés ( en étant absent de [..] ), ce serait simple:
    (/[..]{5})?
    ([..]+)

    signifierait que le motif /[..]{5} pourrait être facultatif mais qu'en cas de présence de / en tant que premier caractère à la position courante, il devrait être obligatoirement suivi de 5 caractères [..] : cela signifierait qu’il ne pourrait pas y avoir moins de 5 caractères [..] à la suite d’un / comme premier caractère.

    Cependant, le caractère / est présent dans [./.]
    Donc
    (/[./.]{5})?
    ([./.]+)

    impose toujours 5 caractères [./.] après un / en premier caractère;
    mais ce motif est facultatif et s'il y a / en premier caractère suivi de moins de 5 caractères, alors ([./.]+) qui suit entre en jeu et matche avec aussi bien avec le premier caractère / que les moins de 5 autres.

    Ce qui revient à dire que le nombre de caractères [./.] qui suivent un premier / peut être quelconque: plus, ou moins, de 5 caractères [./.] après un premier / , ça n’a aucune importance => (/[./.]{5})? ne sert strictement à rien







    (:[\d]{2,5})?
    pas besoin d’entourer \d de crochets. Le compilateur de regex sait lire, il interprète les deux caractères successifs \ et d comme UN symbole. Ça ne sert qu’à alourdir une RE qui est déjà bien confuse.
    => (:\d{2,5})?

    Idem pour ([\w]+) => (\w+)







    ([\w.]{3,8})+
    Appelons X l’expression [\w.]{3,8} : elle représente une succession de 3 à 8 caractères dans lesquels on peut trouver des caractères alphanumériques, l’underscore et le point. Le point n’est pas obligé d’apparaître dans une telle succession de 3 à 8 caractères (les autres non plus d'ailleurs)

    Or le + dit qu’une succession de N successions de type X peut exister, mais il ne sera autorisé que des chaînes de N fois 3 à 8 caractères de type [\w.]
    C'est à dire que ne seront autorisées que les successions de NN caractères où NN devra être divisible par 3 ou 4 ou 5 ou 6 ou 7 ou 8.
    Or mine de rien il y beaucoup de nombres qui ne sont pas dans ce cas, c'est à dire qui ne sont divisibles par aucun des chiffres 3,4,5,6,7,8. Un petit programme permet de trouver le début de cette série:
    1 2 11 13 17 19 22 23 26 29 31 34 37 38 41 43 46 47 53 58 59 61 62 67 71 73 74 79 82 83 86 89 94 97 101 103 106 107 109 113 118 121 122 127 131 134 137 139 142 143 146 149 151 157 158 163 166 167 169 173 178 179 181 187 191 193 194 197 199 202 206 209 211 214 218 etc

    Je ne pense pas que tu voulais interdire les chaîne de ces longueurs là, ça n’a aucun sens.
    Je pense que tu voulais spécifier qu’il peut y avoir entre 3 et huit groupes de caractères alphanumériques séparés par des points. Pourquoi limiter à 8, c’est bizarre, mais bon.....
    En tous cas, quel que fùt l’objectif, c’est raté.






    Question au passage: à quoi servent toutes ces parenthèses ? Il y a vraiment besoin de capturer tous ces groupes définis, y compris le groupe 11 qui doit attraper un seul caractère ?




    Voilà pour la RE



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


    D’autre part, ta “solution“ marche mais je pense que tu n’as pas saisi pourquoi.

    Ta "solution" utilise une assertion arrière, mais as tu remarqué que la regex marche même si on enlève cette assertion ?


    En fait, la dernière partie de la regex, codée par
    (([\w:#@&%=/;$~_?\+-.]){15})
    (on a vu que le {1} est inutile)
    ne peut pas matcher avec un blanc ou avec /Donc cette partie de la regex détermine le moteur à arrêter sa progression devant le ’<’ de ’</p>’ dans le premier cas
    et devant le blanc dans le deuxième cas. C’est tout; l’assertion arrière est vérifiée mais ce n’est pas elle qui joue.



    Je ne sais pas si ton utilisation de cette assertion arrière provient de mon précédent post, en tous cas ce dernier était idiot puisque ta RE dans ton premier post marchait bel et bien, contrairement à ce que tu as écrit dans #1.
    Je ne m’en suis pas aperçu parce que j’ai été trop feignant pour faire tourner un code avec ta RE en me basant sur ce que tu avais écrit.






    Finalement dans cette file, il y a une RE qui marche dans le #1 et dont tu as cru qu'elle ne marchait pas, on se demande pourquoi.

    Puis, sans doute pour faire marcher une RE qui était correcte, tu as fait des ajouts de "(&lt;){1}" et "[\s]{1}" , ce qui l’a rendue cette fois inefficace car ces ajouts ne pouvaient matcher avec rien. Au passage tu as introduit des lignes supplémentaires et des modifications baroques.

    Et enfin dans le #5 on se retrouve avec une RE prétenduement corrigée par un ajout supplémentaire qui n’est pas la vraie cause agissante de la correction mais qui a pour vertu d'être vérifiée tout en remplaçant les ajouts précédents qui étaient responsables du déréglement.

    C’est du bricolage complet.

Discussions similaires

  1. [Regex] chaîne sans balise html
    Par Casp dans le forum Général Java
    Réponses: 10
    Dernier message: 30/05/2012, 14h38
  2. Réponses: 2
    Dernier message: 11/06/2008, 09h32
  3. [Regex] Suppression de blocs de balises HTML
    Par alband85 dans le forum Général Java
    Réponses: 3
    Dernier message: 15/05/2008, 01h54
  4. problème regex suppression balises HTML
    Par crazydindon dans le forum Langage
    Réponses: 6
    Dernier message: 11/09/2007, 14h39
  5. [Regex] Balises Html
    Par onegamer dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 09/08/2005, 16h34

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