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 :

Aide pour écrire une regex


Sujet :

Langage PHP

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2016
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2016
    Messages : 2
    Points : 2
    Points
    2
    Par défaut Aide pour écrire une regex
    Bonjour à tous,
    J'essaie de parser avec une regex la chaîne suivante :
    field1,field2,field3(subfield1,subfield2) pour générer un tableau du type :
    [field1,field2,field3 => [subfield1,subfield2]]
    J'y arrive facilement pour récupérer les champs de niveau 1 mais j'arrive pas à récupérer les champs de niveau 2.

    Si quelqu'un a une idée je suis preneur.
    Merci

  2. #2
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    L'écriture de la regex en elle-même n'est pas bien compliqué, ici la difficulté c'est surtout de trouver une méthode maline pour former le tableau avec le format donné.

    Si le format de la chaîne est fixe (toujours le même nombre de champs) on décrit la chaîne complète avec des captures nommées pour ne pas s'emmêler les pinceaux:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $str = 'field1,field2,field3(subfield1,subfield2)';
    if (preg_match('~\A(?<f1>[^,]*),(?<f2>[^,]*),(?<kf3>[^(]*)\((?<sf1>[^,]*),(?<sf2>[^,]*)\)\z~', $str, $m)) {
        $result = [ $m['f1'], $m['f2'], $m['kf3'] => [ $m['sf1'], $m['sf2'] ] ];
    }
     
    print_r($result);

    Une solution plus élégante avec une chaîne formatée:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $str = 'field1,field2,field3(subfield1,subfield2)';
    $format = '%[^,],%[^,],%[^(](%[^,],%[^)])';
    $result = [];
    sscanf($str, $format, $result[], $result[], $key, $result[$key][], $result[$key][]);
    print_r($result);

    En PHP 7, grâce au changement de sens d'affectation des paramètres de list(), on peut aussi écrire:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    list($result[], $result[], $key, $result[$key][], $result[$key][]) = sscanf($str, $format);
    ce qui est plus lisible, mais ce comportement pourrait être amené à changer dans une version future (mais ça m'étonnerait).

    Si le nombre de champs (et de sous-champs) est indéterminé, on peut procéder avec preg_match_all. La différence majeur avec la version preg_match est que le format de la chaîne n'est plus vérifié de bout en bout:

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    preg_match_all('~([^,()]+)(?:\(([^)]*)\))?~', $str, $matches, PREG_SET_ORDER);
     
    foreach($matches as $m) {
        if (isset($m[2]))
            $result[$m[1]] = explode(',', $m[2]);
        else
            $result[] = $m[1];
    }

    On peut toutefois la vérifier en procédant comme ceci:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $result = false;
     
    if ( preg_match_all('~\G([^,()]*)(\([^)]*\))?(,|\z)~', $str, $matches, PREG_SET_ORDER) && empty(end($matches)[3]) ) {
        $result = [];
        foreach($matches as $m) {
            if (empty($m[2])) // on n'utilise plus isset(). Puisqu'il y a une 3e capture, l'item 2 existe toujours.
                $result[] = $m[1];
            else
                $result[$m[1]] = explode(',', trim($m[2], '()'));
        }
    }
     
    var_dump($result);

    \G réussit au début de la chaîne ou à la suite du match précédant (ce qui fait qu'il ne peut y avoir de "trous" entre les résultats), puis le 3e groupe de capture prend soit le séparateur de champs (la virgule), soit l'ancre de fin de chaîne \z (dans ce cas le groupe est vide, et c'est précisément ce que contrôle empty(end($matches)[3]) pour s'assurer que la fin de la chaîne a bien été atteinte).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

Discussions similaires

  1. Besoin d'aide pour écrire une regex
    Par kao98 dans le forum Général Python
    Réponses: 4
    Dernier message: 05/03/2010, 15h59
  2. [RegEx] Aide pour créer une regex
    Par lemirandais dans le forum Langage
    Réponses: 2
    Dernier message: 02/08/2009, 16h40
  3. aide pour écrire une requete imbriquée
    Par DonKnacki dans le forum Langage SQL
    Réponses: 6
    Dernier message: 07/03/2008, 15h13
  4. [RegEx] Besoin d'un coup de main pour écrire une regex
    Par gaboo_bl dans le forum Langage
    Réponses: 7
    Dernier message: 18/08/2006, 17h53
  5. Aide pour écrire une requête complexe
    Par julienbdx dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 29/11/2005, 16h58

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