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 :

Chaîne nom + valeur entre crochets [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Mai 2002
    Messages
    638
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 638
    Points : 408
    Points
    408
    Par défaut Chaîne nom + valeur entre crochets
    Bonjour,

    Qui peut m'aider pour une expression régulière ?

    J'ai des chaînes de la forme 'nomplugin[X.Y]' contenant un nom de plugin suivi optionnellement d'une version entre crochets (X.Y). Je cherche une expression régulière pour extraire le nom et la version. Il n'y a pas de contrainte pour le format du numéro de version.

  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
    Présenté comme ça, ça n'a pas l'air bien difficile. Peux-tu:
    • Poster le code PHP d'un tableau d'exemples significatifs réalistes (avec les divers cas de figure).
    • Montrer ce que tu as essayé, même si ça marche pas et dire ce qui te bloque précisément.


    Pourquoi n'as tu pas tenté de le faire sans expression régulière ?
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Mai 2002
    Messages
    638
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 638
    Points : 408
    Points
    408
    Par défaut
    Oui, ça peut se faire très facilement sans expression régulière :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    list( $name, $version ) = explode( '[', $pluginName );
    $version = substr( $version, 0, -1);

    Je me demandais s'il y avait une solution plus élégante avec une expression régulière.

    Exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $plugins = [
        'contactform[1.1]',
        'limit_login_attempts[0.5]',
        'maintenance_mode[1.0]',
        'blog'
    ];
    Cela fonctionne presque avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_split("/[\[\]]+/", $pluginName);
    Mais le tableau contient une entrée supplémentaire vide.

  4. #4
    Membre émérite
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 756
    Points : 2 990
    Points
    2 990
    Par défaut
    Bonsoir

    Ceci devrait faire le job: https://regex101.com/r/DXdf4o/4

    L'expression étant ^(?P<plugin>[^\[\]]*)(\[(?P<version>[0-9.]*)\])?$.

    Tu dois traiter le match 1 (le nom du plugin) et le match 3 (la version).
    Christophe (cavo789)
    Mon blog, on y parle Docker, PHP, WSL, Markdown et plein d'autres choses : https://www.avonture.be

  5. #5
    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
    En fait ce qui est embêtant, c'est que quelque soit la méthode employée (sans regex, preg_split, preg_match), il faut régler d'une manière ou d'une autre le cas où il n'y a pas de numéro de version (ce qui aboutit à un warning).

    C'est possible avec preg_match en utilisant un groupe dit branch reset (?| ...(...)... | ...(...)... ) dans lequel les groupes de captures portent les mêmes numéros (ou noms dans le cas de captures nommées) dans chaque alternative. Il suffit alors de créer une alternative où le groupe de capture ne capture qu'une chaîne vide pour les cas où il n'y a pas de numéro de version:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    preg_match('~\A [^]]+ (?= (?| \[ ( .* ) ] | ( ) ) \z ) ~x', $plugin, $m);
     
    [$name, $version] = $m;
    L'éventuelle partie version est ici décrite à l'intérieur d'un test avant (lookahead) (?=...) afin qu'elle n'apparaisse pas dans la correspondance globale; et comme preg_match peuple sa variable résultat avec la correspondance globale suivie des groupes de captures, on obtient pile-poil le tableau qu'il faut.




    Si tu préfères obtenir null à la place d'une chaîne vide lorsqu'il n'y a pas de version, tu peux aussi utiliser un simple groupe non-capturant optionnel avec le flag PREG_UNMATCHED_AS_NULL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    preg_match('~\A [^]]+ (?= (?: \[ ( .* ) ] )? \z ) ~x', $plugin, $m, PREG_UNMATCHED_AS_NULL);
     
    [$name, $version] = $m;
    Avec ce flag, même si le groupe de capture est situé en fin de pattern, et est optionnel du fait de sa situation (ici parce qu'il est dans le groupe non-capturant optionnel), son item sera défini dans le tableau de résultats quoi qu'il arrive. Ce n'est pas le cas sans cette option: lorsqu'un groupe optionnel non satisfait est en fin de pattern, l'item du groupe de capture n'existera tout simplement pas dans le résultat (ce qui provoquera le warning lors de l'affectation de $version).




    Variantes pour obtenir un tableau associatif grâce au captures nommées. Ce qui est agaçant avec les captures nommées en PHP, c'est qu'elle restent numérotées quoi qu'on fasse et que le résultat contient alors ces captures numérotées avec en plus de manière dupliqué, les captures nommées comme des alias: il n'existe pas de flag pour n'avoir que les captures nommées dans le résultat. Pour ce faire, on est obligé d'utiliser array_filter.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    preg_match('~\A (?<name>[^]]+) (?: \[ (?<version>.*) ] )? \z ~x', $plugin, $m, PREG_UNMATCHED_AS_NULL);
     
    $result = array_filter($m, fn($k) => !is_numeric($k), ARRAY_FILTER_USE_KEY);
    pour obtenir null comme tout à l'heure.

    Ou:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    preg_match('~\A (?<name>[^]]+) (?| \[ (?<version>.*) ] | () ) \z ~x', $plugin, $m);
     
    $result = array_filter($m, fn($k) => !is_numeric($k), ARRAY_FILTER_USE_KEY);
    pour obtenir une chaîne vide avec le branch reset.

    Ou encore en utilisant le modificateur J qui autorise la duplication des noms de groupe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    preg_match('~\A (?<name>[^]]+) (?: \[ (?<version>.*) ] | (?<version>) ) \z ~Jx', $plugin, $m);
     
    $result = array_filter($m, fn($k) => !is_numeric($k), ARRAY_FILTER_USE_KEY);
    Avant PHP 7.2, il n'est pas possible d'utiliser ce modificateur de manière globale, par contre on peut le glisser dans le scope d'un groupe non capturant de cette façon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match('~\A (?<name>[^]]+) (?J: \[ (?<version>.*) ] | (?<version>) ) \z ~x', $plugin, $m);
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

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

Discussions similaires

  1. [RegEx] Trouver la valeur d'une occurence entre crochets
    Par flashnet dans le forum Langage
    Réponses: 2
    Dernier message: 12/01/2012, 09h47
  2. Réponses: 5
    Dernier message: 27/09/2005, 17h25
  3. valeur entre 0000000a et 9999999z
    Par niglo dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 30/06/2005, 09h37
  4. transfert de valeurs entre fonctions js et asp
    Par ericmart dans le forum ASP
    Réponses: 5
    Dernier message: 10/03/2005, 16h18
  5. Passage de valeurs entre fenêtres différentes
    Par Amnesiak dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 16/02/2005, 15h10

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