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 :

[RegExp] Problèmes expressions régulières


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 137
    Par défaut
    Fladnag tes 2 solutions me renvoyent comme résultats les 1ères lettres de mes src seulement.

    Sinon, les assertions et les masques conditionnels m'interresse... mais j'ai absolument rien compris ^^

    Je galère deja assez avec des expressions de bases, alors ajouter ça en plus :s

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 45
    Par défaut
    Essaye la méthode de crotte
    il a tester sa marche normalement

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 137
    Par défaut
    Non, elle ne fonctionne pas s'il n'y a ni ' ni " et aussi s'il y a des element avant src (comme border=0) ca ne fonctionne pas non plus

  4. #4
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    ok, on doit pouvoir blinder avec ca :

    '/<img[^\'">]+src=[\'"]?([^\'">]+)[\'"]?[^>]*>/iU'

    et

    '/<img[^\'">]+src=([\'"]?)([^\'">]+)\1[^>]*>/iU'

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 137
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    preg_match_all ('/<img[^\'">]+src=[\'"]?([^\'">]+)[\'"]?[^>\'"]*>/iU', $corps, $out, PREG_SET_ORDER);
    Avec ça j'ai un truc pas mal.
    Que j'ai quelque chose avant ou apres, il m'affiche la source de l'image sans les ' ou les ".
    Le problème, si le src n'a ni ' ni ", il m'affiche juste la 1ere lettre :s

    On est bientot au bout ^^

  6. #6
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    oué... sauf que je vois pas comment faire sans utiliser d'assertions ;o)

    le probleme est dans la fin du masque :

    [\'"]?([^\'">]+)[\'"]?[^>\'"]*

    Si il n'y a pas de " ou de ' , ca donne :

    ([^\'">]+)[^>\'"]*

    ce qui veut dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    capture 1 ou n caracteres qui ne sont pas ', " ou > et qui sont suivis de n'importe quel caracteres exceptés >, ' et "
    Alors qu'il faudrait dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    * Si on a des " ou ' : capture 1 ou n caracteres qui ne sont pas ', " ou > et qui sont suivis de n'importe quel caracteres exceptés >, ' et "
    * Si on a pas de " ou ' : capture 1 ou n caracteres jusqu'au premier espace ou au premier >
    Si tu dit qu'il est impossible qu'une image contienne des espaces... ce qui est le cas si l'url de l'image est bien formée puisqu'en principe il doit etre remplacé par %20, tu peux ajouter un espace dans la parenthese capturante :

    [\'"]?([^\'"> ]+)[\'"]?[^>\'"]*

    Il est possible que ca ne suffise pas...
    tu peux essayer de rajouter aussi un espace dans la classe de caracteres suivante :

    [\'"]?([^\'"> ]+)[\'" ]?[^>\'"]*

    Si ca ne marche toujours pas, il va falloir se tourner vers les assertions...

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 137
    Par défaut
    Toujours pareil, même avec les espaces.
    Ce que je ne comprend pas, c'est pourquoi il s'arrete apres la 1ere lettre, pourtant ce n'est pas un caractère spécial (' " ou <).

    Ca ne me dérange pas d'utiliser les assertions, il faut juste que j'arrive a comprendre comment s'en servir

    En tout ca merci beaucoup d'essayer de m'aider

  8. #8
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    c'est normal qu'il s'arrete a la premiere lettre :

    quand tu as ca :

    [\'"]?([^\'">]+)[\'"]?[^>\'"]*

    sans les guillemets ni apostrophes, qui sont optionnels, ca donne ca :

    ([^\'">]+)[^>\'"]*

    on lui demande donc 1 ou n caracteres qui ne sont pas ', " ou >
    suivi de 0 ou n caracteres qui ne sont pas > ' "

    donc avec l'option U, il fait le moins de boulot possible et ne prend que le premier caracteres puisque les autres satisfont le masque suivant.

    Donc allons y avec les assertions et les sous masques conditionnels ;o))

    Apres quelques tests, voici le résultat ;o)
    testé donc il fonctionne ;o)

    Les seuls cas ou il renvoi "ERREUR" est le cas ou on as :
    <img src=avec espace.gif>
    ce qu'un navigateur normal ne devrait pas afficher non plus, donc ca me parait bien ;o)

    Attention... voila la solution ;o)
    (et livrée avec le jeu de test en plus ;o)

    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
    <?php
     
    $preg = '/<img[^>]+src=([\'"])?([^\'">]+)(?(1)\1|[ >])/iU';
     
     
    $img = 'truc.gif';
    //$img = 'avec espace.gif';
    //$img = 'avec%20%vrai%espace.gif';
     
    $test = array(
    "<img src=$img>",
    "<img src=$img >",
    "<img src=$img border=0>",
    "<img src=\"$img\">",
    "<img src=\"$img\" >",
    "<img src=\"$img\" border=0>",
    "<img src='$img'>",
    "<img src='$img' >",
    "<img src='$img' border=0>",
    "<img alt='machin' src='$img' title='chouette' border=0>",
    );
     
     
    foreach($test as $texte) {
    	preg_match_all ($preg, $texte, $resultats, PREG_SET_ORDER);
     
    	echo htmlspecialchars($texte).' : <br><pre>';
    	$resultats = @array_map('htmlspecialchars',$resultats[0]);
    	@var_dump($resultats);
    	if (@$resultats[2] !== $img) {
    		echo "<b>ERREUR</b>";
    	}
    	//@var_dump($resultats[2]);
    	echo "</pre><hr>";
    }
     
    ?>

    Donc en gros ce que ca donne en langage humain :

    * on recherche "<img"
    * on recherche 1 ou n caracteres qui ne soient pas >
    * on recherche "src="
    * on recherche eventuellement le caractere ' ou " et on l'enregistre sous le nom "1"
    * on recherche 1 ou n caracteres qui ne soient ni ', ni ", ni > et on les enregistrent sur le nom "2"
    (c'est la que ca se complique ;o) :
    * On evalue une condition : "(?(condition)masque_si_vrai|masque_si_faux)"
    ° La condition est : 1 ce qui veux dire : "Si on a trouvé quelque chose qui a le nom "1" (puisque on pouvait eventuellement ne rien capturer)
    ° Le masque_si_vrai est :
    "\1" ce qui correspond a : le caractere capturé (référence arriere \1) ce qui suffit pour etre sur qu'on est arrivé au bout du nom du fichier.
    ° Le masque_si_faux est :
    "[ >]" ce qui correspond a : un caractere qui est soit espace soit >. On a pas besoin de verifier qu'on va jusqu'a la fin de la balise, car on pourrait avoir d'autres attributs entre temps. Le fait de verifier qu'on a un espace suffit.
    Amuse toi bien ;o)

  9. #9
    Fabouney
    Invité(e)
    Par défaut
    Merci beaucoup Fladnag,

    j'viens de comprendre les assertions, c'est pas si sorcier, mais faut bien savoir ou placer la condition est sur quoi effectuer le test lol.
    merci pour blue ca me servira aussi tout ca.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 137
    Par défaut
    C'est super ca Fladnag !

    Merci beaucoup d'avoir passé du temps pour m'aider

    C'est vrai qu'avec un bel exemple bien expliqué, on comprend tout de suite mieux ^^

  11. #11
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    Salut

    Désolé pour le décalage dans la réponse, c'est que je n'ai pas le Net chez moi...

    Je reviens sur ma proposition d'hier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match_all('/<img.+src=([^>]+)[ \/]?>/iU', $corps, $regs, PREG_SET_ORDER);
    Oui, effectivement, elle inclut les guillemets (simples, doubles ou inexistants) car, AMHA, c'est la méthode la plus simple et elle te permet, comme je l'ai dit hier, de faire un traitement ultérieur (à la regexp) afin de rectifier les syntaxes foireuses (c'est-à-dire de remplacer les guillemets simples par des doubles ou juste de les ajouter s'ils font défaut).
    Ce traitement n'est pas des plus complexes : un bête test sur le premier et le dernier caractères.
    Je pense que ça vaut le coup.

    [Edit]
    Citation Envoyé par Fladnag
    donc avec l'option U, il fait le moins de boulot possible et ne prend que le premier caracteres puisque les autres satisfont le masque suivant.
    N'est-ce pas l'inverse ? Il me semblait que "U" signifiait Ungreedy, soit "allez, force-toi un peu mon vieux et donne-moi tout ce que tu trouves".

  12. #12
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    sur php.net :
    U (PCRE_UNGREEDY)

    Cette option inverse la tendance à la gourmandise des expressions rationnelles. Vous pouvez aussi inverser cette tendance au coup par coup avec un ?. De même, si cette option est activée, le ? rendra gourmand une séquence. Cette option n'est pas compatible avec Perl. Elle peut aussi être mise dans le masque avec l'option ?U dans le pattern ou par un point d'interrogation avant le quantifieur (.e.g. .*?).
    Cela veux dire que l'expression va en faire le moins possible justement.

    Un exemple extrement simple ou l'utilité de U est flagrante est celle ci :

    Si on considere l'expression reguliere : /<(.+)>/

    qui correspond a rechercher ce qu'il y a dans une balise en gros.

    Et qu'on lance ca sur :
    <b><i>a</i></b>

    ca va capturer "b><i>a</i></b"
    car justement il prend le maximum de caracteres

    Si on ajoute l'option U, il va capturer :
    b, i, /i et /b ce qui correspond a ce que l'on cherche ;o)

    PS : le probleme de gerer les séparateurs ulterieurement avec ta regexp c'est que si tu as :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <img src="avec espace.gif">
    tu va capturer la chaine :
    ;o)

  13. #13
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    Ouais, j'ai l'impression que c'était une nuance de vocabulaire.

    Dans ma tête à moi, "ungreedy" veut dire "allez, sois pas radin", alias "fais le plus de boulot possible" ou encore "donne-moi le plus de résultats possibles".

    Selon tes termes, "ungreedy" signifie "fais-en le moins possible", sous-entendu "je veux que chaque résultat soit le plus court possible".

    En fait, nous étions d'accord.
    Ai-je bon ?


    [Edit] En gérant les guillemets par un traitement ultérieur, ma regexp va sortir "avec espace.gif" de la chaîne <img src="avec espace.gif">.
    L'idée est de trim() la chaîne avec ' et " comme paramètres optionnels, puis d'ajouter des " en début et fin de chaîne.

  14. #14
    Membre Expert

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Par défaut
    Citation Envoyé par Kirkis
    [Edit] En gérant les guillemets par un traitement ultérieur, ma regexp va sortir "avec espace.gif" de la chaîne <img src="avec espace.gif">.
    L'idée est de trim() la chaîne avec ' et " comme paramètres optionnels, puis d'ajouter des " en début et fin de chaîne.
    Nan, le probleme c'est qu'il va s'arreter au premier espace a cause de [ \/]?, c'est pour ca qu'il ne retournera que
    "avec

    et pas le reste. De toute facon, si t'as <img src="avec machin.gif" border=0>, ca ne marchera forcement pas puisque si il s'arrete a l'espace, ca renvoi <<"avec>> et si il ne s'arrete pas a l'espace, il renvoi <<"avec machin.gif" border=0>>

    greedy veux dire gourmand ou avide, ungreedy correspond donc au contraire, soit "si tu trouve un resultat, ne vas pas regarder si une chaine plus grande satisfait le masque", ce qui ne veux pas dire "ne regarde pas le reste de la chaine" (sinon il ne renverrais qu'un seul résultat ;o)

  15. #15
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    Lol oui, en effet, tu as raison pour l'espace.
    J'arrête de faire des propositions puisque le souci originel est réglé... J'aurais bien mis [ \/]? dans la parenthèse en ajoutant / à la liste des caractères que trim() devra supprimer. Ça oblige à le concaténer à la fin avec les guillemets mais ça permet, encore une fois, de corriger la syntaxe des balises incorrectes.

    Tu as raison à propos des autres attributs. C'est le souci causé par l'absence possible de guillemets.
    Une solution consisterait à effectuer deux passes : la première pour les images ayant une source sans guillemets (donc pas d'espace autorisés dans le nom de fichier image) puis une seconde comportant les guillemets (et donc aussi les espaces à l'intérieur).

    Sinon, c'est bien ce que je pensais, c'était sur la sémantique que nous n'étions pas d'accord mais nous voyions le même effet pour U.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 2
    Dernier message: 27/10/2011, 15h58
  2. Réponses: 2
    Dernier message: 26/07/2011, 11h02
  3. Réponses: 3
    Dernier message: 31/08/2010, 10h39
  4. [regexp] petit problème d'expression régulière
    Par LE NEINDRE dans le forum Langage
    Réponses: 14
    Dernier message: 16/12/2005, 10h33
  5. [langage] [RegExp] Question d'expression régulière
    Par cloogy dans le forum Langage
    Réponses: 5
    Dernier message: 08/10/2003, 09h29

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