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 :

preg_match all d'une chaine mais sans prise en compte si dans une parenthèse [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Juin 2004
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms

    Informations forums :
    Inscription : Juin 2004
    Messages : 88
    Points : 74
    Points
    74
    Par défaut preg_match all d'une chaine mais sans prise en compte si dans une parenthèse
    Bonsoir tout le monde,

    je reviens vers vous pour modifier un preg_split. Je pense me tourner du coup vers un preg_match_all, la structure de la pattern se compliquant un peu?!

    voilà jusqu'à présent, je divisais ma chaîne de caractères avec preg_split en repérant ; (point virgule) et , (virgule)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $arrIngr = preg_split("/([;,]\D)+/", $ingredient->ingr);
    Mais il s'avère parfois que dans la chaîne il y ai un des 2 caractères à l'intérieur d'une parenthèse mais je ne veux pas que le découpage soit pris en compte dans ces parenthèses!

    j'ai regardé et testé pas mal de choses mais je n'y arrive pas, donc je pensais m'orienter avec la fonction preg_match_all, peut m'importe!
    mais là pareil je ne comprends pas comment lui dire que si sur la chaîne en cours il trouve la virgule dans la parenthèse il l'ignore. J'ai tenté de mettre des assertions (je ne connaissais pas), mais sans succès non plus.

    exemple: foo, bar, foo (foo, bar, foo), bar, bar (foo)
    je veux comme résultat:
    foo
    bar
    foo (foo, bar, foo)
    bar
    bar (foo)
    Merci encore pour votre aide !

  2. #2
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 857
    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 857
    Points : 6 555
    Points
    6 555
    Par défaut
    Ça tombe bien les assertions ne servent à rien pour ce cas précis. Tu peux effectivement utiliser preg_match_all en décrivant les items au lieu du séparateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $arrIngr = [];
    if (preg_match_all('~[^,;(]+(?:\([^)]*\)[^,;(]*)*|(?:\([^)]*\)[^,;(]*)+~', $ingredient->ingr, $matches))
        $arrIngr = array_map('trim', $matches[0]);

    La pattern semble un peu longue mais est plutôt simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ~
        # première branche: l'item ne commence pas par une parenthèse
        [^,;(]+ # au moins un caractère n'étant pas une virgule, un point-virgule ou une parenthèse
        (?: # groupe non-capturant
            \( [^)]* \) # contenu entre parenthèses (on ignore les virgules et point-virgules)
            [^,;(]*      # suivi d'éventuels caractères 
         )* # on répète le groupe autant de fois qu'il y a de parenthèses.
      | # deuxième branche: l'item commence par une parenthèse
        (?: \([^)]*\) [^,;(]* )+ # même groupe que précédemment sauf qu'il est répété au moins une fois
    ~
    Tu peux aussi l'écrire comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $arrIngr = [];
    if (preg_match_all('~(?=[^,;])[^,;(]*(?:\([^)]*\)[^,;(]*)*~', $ingredient->ingr, $matches))
        $arrIngr = array_map('trim', $matches[0]);
    Avec une seule branche, mais il faut ajouter un lookahead (test avant) pour ne pas matcher la chaîne vide.

    Ou encore:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $arrIngr = [];
    if (preg_match_all('~(?:[^,;(]+|\([^)]*\))+~', $ingredient->ingr, $matches))
        $arrIngr = array_map('trim', $matches[0]);
    Mais cette formulation n'est pas très efficace.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Membre régulier
    Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Juin 2004
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms

    Informations forums :
    Inscription : Juin 2004
    Messages : 88
    Points : 74
    Points
    74
    Par défaut
    Merci beaucoup! je ne pensais pas avoir une réponse aussi précise et bien détaillée!
    Que dire... BRAVO!
    le reste était prêt, j'ai vu 2 3 anomalies que je corrigerais à la main et modifierais le pattern pour les prochaines fois

    pour la petite histoire j'étais "pas loin" du dernier exemple je ne maîtrise que les rudiments tellement j'en fais peu et du coup j'ai même pas pensé à tout décortiquer et utiliser le group (?: correctement, je mettais mes caractères de séparation [,;] en dehors, bref j'avais zappé une étape.



    Encore un grand merci à toi!

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 15/10/2015, 13h56
  2. [XL-2010] Suppression d'une ligne dans une feuille A tout en garder les infos dans une feuille B
    Par sebastien_ofs dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 20/01/2015, 12h10
  3. Réponses: 13
    Dernier message: 23/05/2013, 20h38
  4. Réponses: 1
    Dernier message: 31/08/2009, 22h48
  5. [TP]lire une ligne de l'ecran et la stocker dans une chaine
    Par Bleuarff dans le forum Turbo Pascal
    Réponses: 26
    Dernier message: 02/07/2002, 10h08

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