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étecter un motif sur plusieurs lignes [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut Détecter un motif sur plusieurs lignes
    Bonjour,

    Pour trouver le motif ">nom1 DESCRIPTION1" dans une chaîne de caractères , j'utilise le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $chaine= ">nom1 DESCRIPTION1";
    $masque = '/^>([A-Za-z0-9]*)[\s]*[A-Z]*$/';
    $compteur = preg_match($masque,$chaine,$resultat);
    echo '<br>$compteur = "'.$compteur'"'; // Affichage : "$compteur="1"
    print_r(resultat[1]); // Affichage : ">nom1 DESCRIPTION1"
    Jusqu'ici, tout va bien.
    Par contre, si j'ai la chaîne ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2", c'est-à-dire 2 fois le motif de type ">nom DESCRIPTION" , alors $compteur=0 et aucun motif n'est trouvé.

    Sauriez-vous quel masque il faudrait utiliser pour pouvoir détecter le motif ">nom DESCRIPTION" plusieurs fois?

  2. #2
    Membre émérite Avatar de FCYPBA
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 745
    Par défaut
    Bonjour,

    Comment ça va depuis hier ?

    En allant rechercher un peu dans la doc autour de la fonction preg_match tu aurais apercu la fonction preg_match_all qui répond parfaitement à ce que tu veux faire.

    il faut bien entendu modifier un peu la regex pour supprimer les ancrages ( ^ et $ )

    Je te conseille de l'utiliser avec le modificateur PREG_SET_ORDER qui se met en 4ème paramètre

  3. #3
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    t'as essayé ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $masque = '/^[>([A-Za-z0-9]*)[\s]*[A-Z]*]{2}$/';

  4. #4
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    En utilisant la solution de FCYPBA (je viens bien depuis hier, merci lol! Je viens de me rappeler qu'effectivement tu avais répondu à un de mes posts d'hier...) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    $chaine= ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2";
    $motif = '/^>([A-Za-z0-9]*)[\s]*[A-Z]$/';
    preg_match_all($motif,$chaine,$resultat, PREG_SET_ORDER);
     
    $nb = count($resultat[0]);
    echo '<br>$nb = "'.$nb.'"';
    for($j=0;$j<$nb;$j++)
    {
    	echo '<br>$resultat[0]['.$j.'] = "'.$resultat[0][$j].'"';
    	$nom= $resultat[0][j];
    	echo '<br>$nom= "'.$nom.'"';
    }
    j'obtiens le même résultat qu'au départ.


    Et en utilisant le motif de Pymento avec le "{2] à la fin, j'ai une erreur...

  5. #5
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    et si tu remplace le '{2}' par '*' ?

  6. #6
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    En remplaçant par une étoile, j'ai la même erreur : "Compilation failed: unmatched parentheses at offset"...

  7. #7
    Membre émérite Avatar de FCYPBA
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 745
    Par défaut
    Penses à modifier la regex. car avec celle-ci commence en début de chaine ( ^ ) et se termine à la fin ( $ ). Ce n'est pas très bien expliqué.

    Il faut pour que cela fonctionne supprimer les ancres ( ^ et $ )

    la regex devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $motif = '/>([A-Za-z0-9]*)[\s]*[A-Z]/';
    De cette façon, on ne cherche pas un motif commençant forcément au début de chaine

  8. #8
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Citation Envoyé par FCYPBA Voir le message
    Penses à modifier la regex. car avec celle-ci commence en début de chaine ( ^ ) et se termine à la fin ( $ ). Ce n'est pas très bien expliqué.

    Il faut pour que cela fonctionne supprimer les ancres ( ^ et $ )

    la regex devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $motif = '/>([A-Za-z0-9]*)[\s]*[A-Z]/';
    De cette façon, on ne cherche pas un motif commençant forcément au début de chaine




    oui mai de cette façon la chaine " blabla454 >nom1 DESCRIPTION1 toto998" passera.
    Mais en fait c'est pourquoi faire au final ? car après tout dépend de ce que tu veux faire du résultat.

  9. #9
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    Merci pour toutes vos explications, ça m'a bien fait avancer car j'obtiens maintenant :

    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2"
    $nb = 2
    $resultat[0][0] = ">nom1 DESCRIPTION1"
    $resultat[1][0] = ">nom2 DESCRIPTION2"
    $resultat[0][1] = "nom1"
    $resultat[1][1] = "nom2"

    Par contre, comment peut-on faire pour récupérer de la même façon "DESCRIPTION1" et "DESCRIPTION2"?

    Voici le code :

    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
     
    $chaine = ">nom1 DESCRIPTION1  >nom2 DESCRIPTION2"
    echo '<br>$chaine = "'.$chaine.'"';
    $motif = '/>([A-Za-z0-9]*)[\s]*[A-Z]*/';
     
    $nb = preg_match_all($motif,$chaine,$resultat, PREG_SET_ORDER);
     
    echo '<br>$nb = '.$nb;
    for($j=0;$j<$nb;$j++)
    {
    	for($i=0;$i<$nb;$i++)
    	{
    		echo '<br>$resultat['.$i.']['.$j.'] = "'.$resultat[$i][$j].'"';
    	}
    }
    Merci pour votre aide.

  10. #10
    Membre émérite Avatar de FCYPBA
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 745
    Par défaut
    En fait quand tu fais la seconde boucle tu dois utiliser le nombre de captures+1
    Dans ces cas là, il vaut mieux utiliser des foreach

    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
     
    $chaine = ">nom1 DESCRIPTION1  >nom2 DESCRIPTION2"
    echo '<br>$chaine = "'.$chaine.'"';
    $motif = '/>([A-Za-z0-9]*)[\s]*[A-Z]*/';
     
    $nb = preg_match_all($motif,$chaine,$resultat, PREG_SET_ORDER);
     
    echo '<br>$nb = '.$nb;
    for($j=0;$j<$nb;$j++)
    {
    	foreach($resulats[$i] as $elt)
    	{
    		echo '<br>$resultat['.$i.']['.$j.'] = "'.$elt.'"';
    	}
    }

  11. #11
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    Je n'arrive toujours pas à récupérer "DESCRIPTION1" et "DESCRIPTION2".
    En effet, j'obtiens :

    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2"
    $nb = 2
    $resultat = ">nom1 DESCRIPTION1"
    $resultat = "nom1"
    $resultat = ">nom2 DESCRIPTION2"
    $resultat = "nom2"



    Mais j'aimerais obtenir :

    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2"
    $nb = 2
    $resultat[0][0] = ">nom1 DESCRIPTION1"
    $resultat[0][1] = "nom1"
    $resultat[0][2] = "DESCRIPTION1"
    $resultat[1][0] = ">nom2 DESCRIPTION2"
    $resultat[1][1] = "nom2"
    $resultat[1][2] = "DESCRIPTION2"



    Voici mon code:

    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
     
    $chaine = ">nom1 DESCRIPTION1  >nom2 DESCRIPTION2"
    echo '<br>$chaine = "'.$chaine.'"';
    $motif = '/>([A-Za-z0-9]*)[\s]*[A-Z]*/';
     
    $nb = preg_match_all($motif,$chaine,$resultat, PREG_SET_ORDER);
     
    echo '<br>$nb = '.$nb;
     
    foreach($resultat as $v1)
    {
    	foreach($v1 as $v2)
    	{
    		echo '<br>$resultat = "'.$v2.'"';
    	}
    }
    Auriez-vous une idée?

  12. #12
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    En fait je viens de trouver la réponse tout seul!

    Voici le code :

    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
     
    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2";
    echo '<br>$chaine = "'.$chaine.'"';
    $motif = '/>([A-Za-z0-9]*)[\s]*[A-Z]*/';
     
    $nb = preg_match_all($motif,$chaine,$resultat, PREG_SET_ORDER);
     
    echo '<br>$nb = '.$nb;
    for($j=0;$j<$nb;$j++)
    {
    	$chaine_temp = $resultat[$j][0];
    	echo '<br>$chaine_temp = "'.$chaine_temp.'"';
    	$nom_temp = $resultat[$j][$nb-1];
    	echo '<br>$nom_temp = "'.$nom_temp.'"';
    	$chaine_nette_temp = str_replace($nom_temp,"",$chaine_temp);
    	echo '<br>$chaine_nette_temp = "'.$chaine_nette_temp.'"';	
    	$chaine_nettoyee_temp = str_replace('>','',$chaine_nette_temp);
    	$chaine_nettoyee_temp = trim($chaine_nettoyee_temp);
    	echo '<br>$chaine_nettoyee_temp = "'.$chaine_nettoyee_temp.'"';
    }
    Mais sans votre aide, je n'y serais jamais arrivé. Donc un grand merci à tous ceux qui m'ont aidé!

  13. #13
    Membre émérite Avatar de FCYPBA
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 745
    Par défaut
    Pour que le code à base de foreach fonctionne, il suffit d'ajouter des parenthèses capturantes sur le motif [A-Z]* de cette façon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $motif = '/>([A-Za-z0-9]*)[\s]*([A-Z]*)/';
    On obtient ainsi un code beaucoup plus propre, car la version à base de replace ne me plait pas du tout

  14. #14
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    Tu as raison, ça marche encore mieux comme ça!
    Merci encore

    Par contre, comment faire pour récupérer les valeurs retournées?

    Ex :

    Avec ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2";
    echo '<br>$chaine= "'.$chaine.'"';
    $motif = '/>([A-Za-z0-9]*)[\s]*([A-Z]*)/';
     
    $nb = preg_match_all($motif,$chaine,$resultat, PREG_SET_ORDER);
     
    echo '<br>$nb = '.$nb;
    for($j=0;$j<$nb;$j++)
    {		
    	foreach($resultat[$j] as $elt)
    	{
    		echo '<br>$resultat['.$j.'] = "'.$elt.'"';
    	}
    j'obtiens :

    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2"
    $nb = 2
    $resultat[0] = ">nom1 DESCRIPTION1"
    $resultat[0] = "nom1"
    $resultat[0] = "DESCRIPTION1"
    $resultat[1] = ">nom2 DESCRIPTION2"
    $resultat[1] = "nom2"
    $resultat[1] = "DESCRIPTION2".


    Comment faire pour avoir :

    $chaine = ">nom1 DESCRIPTION1 >nom2 DESCRIPTION2"
    $nb = 2
    $resultat[0] = ">nom1 DESCRIPTION1"
    $resultat[0] = "nom1" // Je voudrais mettre "nom1" dans une variable "$nom_temp"
    $resultat[0] = "DESCRIPTION1" // Je voudrais mettre "DESCRIPTION1" dans une variable "$descr_temp"
    $resultat[1] = ">nom2 DESCRIPTION2"
    $resultat[1] = "nom2"
    $resultat[1] = "DESCRIPTION2"

    ?

    Merci de votre aide encore!

  15. #15
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    En fait je viens encore de trouver moi-même : j'ai rajouté un compteur!

    Voici le code :

    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
     
    for($j=0;$j<$nb;$j++)
    {
    	$count=0;
    	foreach($resultat[$j] as $elt)
    	{
    		echo '<br>$resultat['.$j.'] = "'.$elt.'"';
    		if($count==1)
    		{
    			$nom = $elt;
    			echo '<br>$nom = "'.$elt.'"';
    		}
    		if($count==2)
    		{
    			$descr = $elt;					              echo '<br>$descr = "'.$elt.'"';
    		}
    		$count++;
    	}
    }
    Merci encore pour votre aide!

  16. #16
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    En réalité, mon problème n'est pas encore complétement résolu car j'aurais besoin de gérer le multi-lignes.

    Je m'explique : auparavant, avec des lignes du type :
    ">nom1
    DESCRIPTION1
    >nom2
    DESCRIPTION2"

    je n'avais aucun problème car chaque information était sur une ligne différente:
    ainsi, j'avais $nom = "nom1" et $descr = "DESCRIPTION1", par exemple.

    Mais maintenant, j'aimerais utiliser plusieurs lignes pour une information.
    Ex :

    "nom3
    DESCRIPTION TRES LONGUE
    RELATIVE AU NOM3'

    J'aimerais ainsi avoir : $nom = "nom3" et $descr = "DESCRIPTION TRES LONGUE RELATIVE AU NOM3".
    Au lieu de cela, j'ai : $nom = "nom3" et $descr = "DESCRIPTION TRES LONGUE"
    Autrement dit, la variable $descr n'arrive pas à enregistrer une information si elle est sur 2 lignes différentes.

    Pour rappel, mon motif était :
    $motif = '/>([A-Za-z0-9]*)[\s]*([A-Z]*)/';

    J'ai essayé en vain avec le motif suivant :
    $motif = '/>([A-Za-z0-9]*)[\s]*([A-Z]*[\r]*[A-Z]*)/';

    Quelqu'un saurait quel est le bon motif à utiliser pour réussir à récupérer l'information souhaitée dans $descr ?

    Merci d'avance pour votre aide.

  17. #17
    Membre émérite Avatar de FCYPBA
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 745
    Par défaut
    Même si le sujet est résolu, je me permets d'en rajouter encore un peu

    Pourquoi faire une boucle, si tu récupères toutes les valeurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    foreach($resultat as $unresult){
    	$nom = $unresult[1];
    	$descr = $unresult[2];
    }
    pour ton nouveau problème, il suffit de rajouter une classe de caractère dans ta deuxième capture et d'indiquer que la classe espace ( \s ) contiennent également les retours charriots

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $motif = '/>([a-z0-9]*)[\s]*([A-Z\s]*)/m';

  18. #18
    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 : 51
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Par défaut
    Je fais un essai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?php
    $reg = '#>([A-Za-z0-9]++)\s++([^>]+)#';
     
    $str = '>nom1
    DESCRIPTION1
    >nom2
    DESC2 de deux
    >nom3
    DESCRIPTION TRES LONGUE
    RELATIVE AU NOM3';
     
    preg_match_all($reg, $str, $m);
     
    print_r ($m);

  19. #19
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    En fait, FCYPBA, pour "l'ancien problème", le code était :

    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
     
     
    for($j=0;$j<$nb;$j++)
    {
    	$count=0;
    	foreach($resultat[$j] as $elt)
    	{
    		echo '<br>$resultat['.$j.'] = "'.$elt.'"';
    		if($count==1)
    		{
    			$nom = $elt;
    			echo '<br>$nom = "'.$elt.'"';
    		}
    		if($count==2)
    		{
    			$descr = $elt;					              echo '<br>$descr = "'.$elt.'"';
    		}
    		$count++;
    	}
    }
    mais j'ai modifié le code depuis, et donc ma boucle "for" contient d'autres instructions entre les 2 dernières accolades fermantes. En fait, j'ai essayé de mettre ton code préconisé dans le foreach, mais cela ne me renvoie pas les valeurs voulues, ça renvoie tout lettre par lettre. A moins que j'aie mal compris où il fallait mettre le code...

    En tout cas, merci pour ton aide par rapport à mon 2e problème.
    Merci également à s.n.a.f.u. qui vient de se joindre à la conversation.
    J'essaye vos suggestions et je vous tiens au courant.

  20. #20
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    merci! ça marche nickel pour le problème n°2!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Ecrire une requete SQL sur plusieurs lignes
    Par PrinceMaster77 dans le forum ASP
    Réponses: 2
    Dernier message: 15/11/2004, 15h47
  2. Response.Write sur plusieurs lignes
    Par simoryl dans le forum ASP
    Réponses: 2
    Dernier message: 31/08/2004, 23h49
  3. Réponses: 2
    Dernier message: 10/05/2004, 08h55
  4. TDBGrid - Un enregistrement sur plusieurs lignes
    Par BRODU dans le forum Bases de données
    Réponses: 2
    Dernier message: 09/05/2004, 08h53
  5. Define sur plusieurs lignes
    Par Gogoye dans le forum C
    Réponses: 6
    Dernier message: 06/10/2003, 12h45

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