Forum Programmation.autre Captures dans une regexp

Posté par (page perso) .
Tags : aucun
1
18
juil.
2006
Bonjour, dans un programme, je dois récupérer une chaîne du style :
{value='truc';'machin' ; 'kkhjhj'}

(ne me demandez pas pourquoi ce format bizare)
sachant que je peux avoir n paramètres entres crochets.

Le plus simple est de faire une regexp afin de récupérer truc, machin et kkhjhj.

Le problème est que je sais faire
1- Soit une regexp qui match mais ne capture pas
2- Soit une regexp qui match rarement, mais capture

Je m'explique

dans le cas 1, j'utilise la regexp {value=(?:\s*'(\w+)'\s*(?:;|}))*
J'ai alors une capture qui correspond au dernier paramètre, 'kkhjhj'

Dans le cas 2, j'utilise {value='(\w+)'\s*;\s*'(\w+)'\s*;\s*'(\w+)'} et là j'ai mes captures qui vont bien, mais le problème est que je dois connaître à l'avance le nombre de paramètre.

Comment faire pour avoir le beurre et l'argent du beurre, ie. traiter un nombre indéterminé de paramètres et les capturer ?

Merci !
  • # pourquoi tu compliques ?

    Posté par (page perso) . Évalué à 2.

    tu pourrait pas coller dans une variable tout ce qu'il y a entre le = et l'acollade fermante ?, genre
    /{(\w+)=([^}])}/
    en ajoutant les échappements qui manquent surement

    alors $1 contiendra ta valeur, et $2 toutes les valeurs correspondantes.
    ensuite, un split sur $2 avec comme séparateur ";" te donnera toutes les valeurs
    • [^] # Re: pourquoi tu compliques ?

      Posté par (page perso) . Évalué à 1.

      En rajoutant une étoile :
      {(\w+)=([^}]*)}

      et en m'inspirant de l'utile commentaire de jigso, je crois que c'est la moins mauvaise méthode.

      Les regexp me déçoivent...

      « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

  • # Le plus simple est de...

    Posté par . Évalué à 4.

    ... changer de méthode.

    Les regexp, c'est bien, sauf quand ça marche pas... Et en l'occurrence, il est préférable d'utiliser un vrai parser.

    Extrait de perldoc :


    How do I find matching/nesting anything?

    This isn’t something that can be done in one regular expression, no matter how complicated. To find something between two single characters, a pattern like "/x([^x]*)x/" will get the intervening bits in $1. For multiple ones, then something more like "/alpha(.*?)omega/" would be needed. But none of these deals with nested patterns. For balanced expressions using "(", "{", "[" or "<" as delimiters, use the CPAN module Regexp::Common, or see "(??{ code })" in perlre. For other cases, you’ll have to write a parser.
  • # avec awk:

    Posté par . Évalué à 2.

    Ca donnerait un truc comme ça:

    echo "{value='truc';'machin' ; 'kkhjhj'}" | awk -F\; ' {
    gsub(/\{|\}/,"",$0)
    print "Nombre de parametrs: " NF
    for (i=1;i<NF;i++) {
    print "Parametre " i " : " $i
    }
    }'
    le résultat:

    Nombre de parametrs: 3
    Parametre 1 : value='truc'
    Parametre 2 : 'machin'

    A adapter en fonction des besoins.
  • # en sed.

    Posté par (page perso) . Évalué à 3.

    Voici un filtre sed qui fonctionne
    echo "{value='truc'; 'fdsqfsdq'; 'fsfdsq' }" |sed -n "/{value='\w\+'\(\s*;\s*'\w\+'\)\+\s*}/p"
  • # regex + une ligne de code

    Posté par (page perso) . Évalué à 2.

    Prend une regex simple qui trouve ce qu'il y a entre crochet :
    value='truc';'machin' ; 'kkhjhj'

    ensuite, un explode PHP ou Perl et une bidouille, et c'est bon !
    Avec ce genre de pratique j'ai une moulinette qui parse des fichiers .h avec des structs et des enum sans problème.
  • # du sed

    Posté par . Évalué à 1.

    Si je ne dis pas de bétise, tu peux t'appuyer sur les simple cote pour extraire tes paramètres. Un truc comme ça peut-être ? :

    echo "{value='truc';'machin' ; 'kkhjhj'}" | sed -e "s/[^']*'\([^']\+\)'*[^']*/\1\n/g"


    Cette regex laisse une ligne vide à la fin. Ca doit donc pouvoir encore s'améliorer un chouilla ...

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.