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

Python Discussion :

Problème de regex avec des parenthèses imbriquées


Sujet :

Python

  1. #1
    Membre habitué Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Points : 190
    Points
    190
    Par défaut Problème de regex avec des parenthèses imbriquées
    Bonjour,

    j'ai un truc à faire (qui me semble assez simple) avec des regexp, mais ça coince...
    Voici le truc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> import re
    >>> x = re.compile('(=([0-9]+))*')
    >>> x.match('=12=789=30').groups()
    ('=30', '30')
    Je pensais retrouver tous mes nombres (quelque chose comme ça ('=12=789=30','12','789','30') ) mais il ne me renvoie que le dernier !

    Qu'est ce que j'ai raté ?
    [WinXP sp3 / Visual 2005 / Eclipse Ganymede / Python 2.6]
    Hadrien

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Salut,

    Ce que tu veux faire n'est malheureusement pas possible. La documentation du module le précise d'ailleurs :
    If a group matches multiple times, only the last match is accessible:
    >>> m = re.match(r"(..)+", "a1b2c3") # Matches 3 times.
    >>> m.group(1) # Returns only the last match.
    'c3'
    Cette discussion (en particulier le deuxième message) pourrait peut-être t'intéresser...

  3. #3
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    Bonsoir

    Sur l'ensemble d'une chaine, j'aime utiliser la méthode findall

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> nb="\d+" # \d intercepte tout chiffre et + pour 1 fois minimum
    >>> calc="=12=789=30"
    >>> import re
    >>> print re.findall(nb, calc)
    ['12', '789', '30']
    a+
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  4. #4
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Bonjour,



    findall() toute seule n’est pas suffisante car il est probable que sopsag cherche des nombres dans des morceaux de chaîne à l’intérieur de chacun desquels les motifs unitaires se succèdent strictement.



    Par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ch = 'colonie =98=765 charbon=90abcd=9876=345=223 tiroir'
    print re.findall("\d+", ch)
    va certes sortir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ['98', '765', '90', '9876', '345', '223']
    mais ce que veut sopsag est sans doute
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ['=98=765', '=90', '=9876=345=223']
    De plus, il veut le morceau dans lequel les nombres se succèdent avec leur enrobage + les nombres individualisés, donc sans doute ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [['=98=765', '98', '765'], ['=90', '90'], ['=9876=345=223', '9876', '345', '223']]





    Pour répondre à ce double objectif, j’ai finalement trouvé ceci:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ch = 'xyzuv =120=789=907 abcde =9=5=2= huytre'
     
    aRE = '=(\d+)'
    pat = re.compile(aRE)
    print [ [morc]+ pat.findall(morc)
            for morc in ( m.group() for m in re.finditer('(=(\d+))+',ch) ) ]
     
    print '-----------------------------'
     
    aRE = '=(\d+)'
    pat = re.compile(aRE)
    print [ [morc]+ pat.findall(morc)
            for morc in re.findall('((?:=(?:\d+))+)',ch) ]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [['=120=789=907', '120', '789', '907'], ['=9=5=2', '9', '5', '2']]
    -----------------------------
    [['=120=789=907', '120', '789', '907'], ['=9=5=2', '9', '5', '2']]

    Je trouve le deuxième code moins lisible.







    On peut mettre ça sous forme de fonction:

    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
    ch = 'xyzuv =120=789=907 abcde =9=5=2= huytre'
     
    def repeated_chained(aRE,ch):
        if len(re.findall('(?<!\\\\)\(',aRE))==1 and len(re.findall('(?<!\\\\)\)',aRE))==1:
            pat = re.compile(aRE)
            gen_morc =( m.group() for m in re.finditer('('+aRE+')+',ch) )
            return [ [morc]+ pat.findall(morc)
                     for morc in gen_morc ]
     
    print repeated_chained('=(\d+)',ch)
     
    print '-----------------------------'
     
    def repeated_chained(aRE,ch):
        if len(re.findall('(?<!\\\\)\(',aRE))==1 and len(re.findall('(?<!\\\\)\)',aRE))==1:
            pat = re.compile(aRE)
            return [ [morc]+ pat.findall(morc)
                     for morc in re.findall('((?:' + aRE.replace('(','(?:') + ')+)',ch) ]
     
    print repeated_chained('=(\d+)',ch)






    Pourvu que la RE unitaire (aRE) ne comporte qu’un seul parenthésage de capture, on peut alors passer ce qu’on veut à une telle fonction:



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def repeated_chained(aRE,ch):
        if len(re.findall('(?<!\\\\)\(',aRE))==1 and len(re.findall('(?<!\\\\)\)',aRE))==1:
            pat = re.compile(aRE)
            gen_morc =( m.group() for m in re.finditer('('+aRE+')+',ch) )
            return [ [morc]+ pat.findall(morc)
                     for morc in gen_morc ]
     
    dh = 'jhgjfd =567+;=7;++=8764;;++=765+=87;YTRE=98;=654;;;+=452++;IOPUY'
    print repeated_chained('=(\d+)[;+]+',dh)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [['=567+;=7;++=8764;;++=765+=87;', '567', '7', '8764', '765', '87'], ['=98;=654;;;+=452++;', '98', '654', '452']]

  5. #5
    Membre habitué Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Points : 190
    Points
    190
    Par défaut
    Super merci pour toutes ces réponses !!

    Mais celle de Montag
    Citation Envoyé par Montag Voir le message
    Ce que tu veux faire n'est malheureusement pas possible. La documentation du module le précise d'ailleurs :
    est celle que j'attendais (et craignait).

    Une fois de plus, je n'ai pas assez lu la doc...

    En fait, mon exemple avec des '=' était juste là pour illustrer mon besoin.
    Grosso modo, je veux extraire un identifiant suivi d'un nombre quelconque d'entiers séparés par des espaces.

    Du coup, je crois que je vais être obligé de matcher l'identifiant tout seul, puis de faire un findall des mes entiers.
    [WinXP sp3 / Visual 2005 / Eclipse Ganymede / Python 2.6]
    Hadrien

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

Discussions similaires

  1. Problème de style sur un menu avec des listes imbriquées
    Par tarentaise dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 04/08/2011, 13h23
  2. Problème d'affichage avec des Div imbriquées
    Par Arkoze dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 21/02/2011, 17h07
  3. [AC-2007] Problème avec des requêtes imbriquées
    Par triaguae dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 15/02/2011, 14h43
  4. Problème avec des requète imbriquée dans le from
    Par Stouille33 dans le forum Développement
    Réponses: 5
    Dernier message: 23/10/2008, 19h17
  5. Réponses: 6
    Dernier message: 19/10/2004, 13h46

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