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 :

Découpage chaîne (expression régulière?)


Sujet :

Langage PHP

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 207
    Par défaut Découpage chaîne (expression régulière?)
    Bonjour.

    je possède cette chaine.

    <description><![CDATA[<strong>Game</strong>: Omaha <strong>Buy-in</strong>: 1.00 <strong>Entry Fee</strong>: 0.10 <strong>Starting</strong>: 2008-10-31 09:20:00 EST <strong>Max Participants</strong>: 2500]]></description>
    J'aimerais pouvoir récupérer ce qui se trouve chaque fois après la balise fermante </strong>

    Avec toutes les fonctionds preg_....., est ce possible et adapté?

    En effet j'ai du mal à comprendre comment s'en servir.

    Merci.

  2. #2
    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
    Oui, c'est adapté.

    pour récupérer quelque chose il faut utiliser preg_match
    pour récupérer plusieurs choses dans une seule chaine, preg_match_all

    donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    preg_match_all($masque, $chaine, $resultat);
     
    avec 
    $masque = l'expression réguliere (voir plus bas)
    $chaine = ta chaine de caracteres
    $resultat = une nouvelle variable qui sera un tableau de résultats
    Pour le tableau de résultats, affiche le avec :
    echo '<pre>'; var_dump($resultat); echo '</pre>';
    pour comprendre comment il fonctionne

    Pour le masque, tu va avoir besoin de :
    () : pour capturer une portion de chaine
    [] : pour définir une plages de caractere
    ^ : Symbole NOT quand utilisé dans une plage de caractere
    + : Veux dire 1 ou + du caractere qui precede

    Un masque preg est toujours constitué d'un marqueur AVANT et APRES la chaine. Tu peux utiliser "/", "~", "#" ou tout autre caractere, mais je te conseille #, en général ca pose moins de probleme.

    Ton masque sera donc de la forme :
    #...#

    Apres le caractere de fin, tu peux ajouter des options. Pour un comportement "naturel", je te conseille toujours l'option U. Ton masque ressemblera donc a :
    #...#U

    Regardons maintenant ce que tu veux récuperer.
    Tout ce qui est apres une balise </strong>... ok !
    donc ton masque sera de la forme :
    #</strong>...#U

    <, / et > n'étant pas des meta caracteres, tu n'a pas besoin de les échapper.

    Si tu veux récuperer du texte il te faut mettre des (), ton masque sera donc de la forme :
    #</strong>(...)...#U

    Lorsqu'on récupere du texte (avec des parentheses) avec une regexp, il faut toujours penser a ne pas récuperer "trop" de texte. En clair, tu veux récuperer des infos depuis la balise fermante strong jusqu'a... ? Je suppose ici que tu souhaites récuperer ton texte jusqu'a la prochaine balise.
    Ton masque ressemblera donc a :
    #</strong>(...)<#U

    Tu indiques donc que ton texte sera récupéré jusqu'au prochain chevron.
    Ok !
    Maintenant, que souhaites tu récuperer ? (autrement dit : qu'y a t'il a l'interieur des parentheses)
    Une solution "simple" serait : .+ (le point (.) remplace n'importe quel caractere, + veux dire 1 ou plusieurs du caractere qui précéde. ".+" veux donc dire "1 ou plusieurs caracteres, n'importe lesquels"
    Ton masque final serait donc :
    #</strong>(.+)<#U

    et il devrait marcher... grace a l'option U !
    En effet, U veux dire qu'il prend les masques les plus courts possibles.
    Sans l'option U, avec un masque comme ca : #</strong>(.+)<#
    tu aurais eu comme résultat :
    <description><![CDATA[<strong>Game</strong>: Omaha <strong>Buy-in</strong>: 1.00 <strong>Entry Fee</strong>: 0.10 <strong>Starting</strong>: 2008-10-31 09:20:00 EST <strong>Max Participants</strong>: 2500]]></description>
    car rien n'empeche le masque ".+" de correspondre a des balises !

    Cependant, si tu veux éviter completement que cela se produise, tu peux aussi dire que le texte que tu veux récuperer ne DOIT PAS contenir de chevron ouvrant.
    Ainsi, au lieu d'utiliser ".+", tu va dire "1 ou plusieurs caracteres qui ne sont pas un chevron".
    Pour faire ca tu as besoin de construire une classe de caractere ([]) "qui n'est pas (^) un chevron ouvrant" : [^<]
    Tu veux 1 ou plusieurs de ces caracteres, donc le masque sera : [^<]+

    Au final, un masque "plus propre" sera donc :
    #</strong>([^<]+)<#U

    Comme c'est une chaine de caractere, il te faut juste l'entourer d'apostrophe ou de guillemets avant de le passer a preg_match_all :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match_all('#</strong>([^<]+)<#U', $chaine, $resultat);
    http://fr.php.net/fr/preg_match_all
    http://fr.php.net/manual/fr/regexp.reference.php
    http://fr.php.net/manual/fr/referenc....modifiers.php

  3. #3
    Membre chevronné Avatar de LeGilou
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 488
    Par défaut
    félicitations pour la clarté des explications.

    Gillou.

  4. #4
    Membre Expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Par défaut
    Je plussoie,

    moi qui ne me suis jamais penché plus que çà sur les expressions régulières, j'avous avoir compris pas mal de choses dans ton explication, très carthésienne.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 207
    Par défaut
    Merci.

    Je vais lire ça avec attention.

    EDIT: j'ai fait une première lecture, et merci d'avoir était aussi précis

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 207
    Par défaut
    Je viens de tester.
    Ca marche super bien, sauf que j'ai un tout petit problème.

    Mon $chaine vaut cela.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <strong>Game</strong>: Hold'em <strong>Buy-in</strong>: 500.00 <strong>Entry Fee</strong>: 30.00 <strong>Starting</strong>: 2008-11-09 21:30:00 EST <strong>Max Participants</strong>: 2500<strong>Game</strong>: Hold'em
    Le max de participants n'est pas récupéré, je suppose c'est parcequ'il n'y a pas d'espace entre le résultat et le début de l'autre balise strong (pour les autres l'espace est présent).

    Y a t'il une solution pour remédier à cela?

    Merci.

  7. #7
    Membre chevronné Avatar de LeGilou
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 488
    Par défaut
    Ca fonctionne bien chez moi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <?php
    $chaine = "<strong>Game</strong>: Hold'em <strong>Buy-in</strong>: 500.00 <strong>Entry Fee</strong>: 30.00 <strong>Starting</strong>: 2008-11-09 21:30:00 EST <strong>Max Participants</strong>: 2500<strong>Game</strong>: Hold'em";
     
    preg_match_all('#</strong>([^<]+)<#U', $chaine, $resultat);
    echo "<pre>";
    print_r($resultat[1]);
    echo "</pre>";
    ?>
    affiche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Array
    (
        [0] => : Hold'em 
        [1] => : 500.00 
        [2] => : 30.00 
        [3] => : 2008-11-09 21:30:00 EST 
        [4] => : 2500
    )
    Tu n'aurais pas mis un espace après la parenthèse fermante ?

    Gillou

  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
    Citation Envoyé par LeGilou Voir le message
    Ca fonctionne bien chez moi
    idem ^^

    En effet, ca ressemble a un probleme d'espace dans le masque que tu as écrit je pense

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 207
    Par défaut
    Logique.

    Je viens de comprendre.
    la chaine sur laquelle je travaille vaut cela en fait!!!
    En effet je parse mon flux RSS enregistrement par enregistrement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string '<strong>Game</strong>: Hold'em <strong>Buy-in</strong>: 3.00 <strong>Entry Fee</strong>: 0.30 <strong>Starting</strong>: 2008-11-05 05:35:00 EST <strong>Max Participants</strong>: 2500' (length=184)
    La est le problème.
    Si vous avez une idée

  10. #10
    Membre chevronné Avatar de LeGilou
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 488
    Par défaut
    par curiosité et pour les prochains lecteurs du forum... c'était quoi ?

    Gillou

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 207
    Par défaut
    Citation Envoyé par LeGilou Voir le message
    par curiosité et pour les prochains lecteurs du forum... c'était quoi ?

    Gillou
    Voir ci-dessus, désolé j'ai édité ma réponse!!!

    Si tu as une solution

  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
    ok, c'est un probleme qu'on rencontre souvent lorsqu'on utilise des regexp... comment faire pour les début et fin de chaine ?

    Là le probleme c'est que ta chaine se termine par l'info que tu veux capturer, il n'y a donc pas le chevron de la prochaine balise et le masque ne correspond pas.

    Tu as 2 solutions :

    A) La solution "bidouille"
    Elle peut paraitre crade... mais elle fonctionne bien ;o)
    l'idée c'est d'ajouter ce chevron a ta chaine avant le parsage. Tu peux donc faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match_all($masque, $texte.'<', $resultats)
    Du coup le masque correspondra aussi au dernier enregistrement de la ligne et ca fonctionnera

    B) La solution "pur regexp"
    Il faut modifier légerement le masque. Au lieu de dire "Recherche tout ce qu'il y a jusqu'au prochain chevron" il faut dire : "Recherche tout ce qu'il y a jusqu'au prochain chevron OU jusqu'a la fin de la ligne !"

    La fin de la ligne en regexp c'est le caractere dollar : $
    Tu pourrais donc tester avec ce masque :
    #</strong>([^<]+)$#U
    Tu ne récupererais QUE le dernier enregistrement.

    Maintenant, si tu veux écrire le OU en regexp, il te faut a nouveau utiliser les parentheses et le symbole "|" (AltGr-6) qui correspond a OU :
    (...|...)
    Ici, tu veux le prochain chevron OU la fin de chaine, donc : (<|$)

    Au final ton masque est donc :
    #</strong>([^<]+)(<|$)#U

    Oui mais... les parentheses servent a capturer une info je t'ai dit, et c'est vrai... les parentheses servent a capturer ET a gérer les OU ;o)
    Du coup, tu va aussi capturer le dernier caractere, ou une chaine vide pour le dernier enregistrement.
    Ca va donc changer légerement le résultat (le tableau principal aura 3 entrées au lieu de 2)

    Si on veux etre perfectionniste, on peut aussi dire EXPLICITEMENT a la parentheses de ne PAS etre capturante ! Ainsi, le résultat ne sera pas changé, mais l'expression réguliere perdra légerement en lisibilité ^^
    En effet, pour faire ca il faut ajouter "?:" juste apres la parenthese ouvrante.
    Du coup le masque serait :
    #</strong>([^<]+)(?:<|$)#U

    Ce qui devient un peu plus complexe... mais est "propre" au niveau regexp ^^

    Fladnag, qui a pris regexp en 2eme langue ;o)

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 207
    Par défaut
    Je te dis un grand merci et bravo.

    20/20.

    Je vais d'ailleurs bookmark cette page.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/03/2007, 17h58
  2. Réponses: 3
    Dernier message: 20/02/2007, 15h48
  3. Réponses: 15
    Dernier message: 17/10/2006, 12h06
  4. Réponses: 4
    Dernier message: 11/08/2006, 13h47
  5. [Regex] Vérifier qu'une chaîne respecte une expression régulière
    Par PeteMitchell dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 13/05/2004, 14h22

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