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 :

using regular expression


Sujet :

Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 4
    Par défaut using regular expression
    Bonjour tout le monde,

    j'ai une question assez bête concernant le module re de la distribution standard.

    Je voudrais trouver l'integer dans e.g. les occurences suivantes:

    - 'molecules 10'
    ou
    - 'molecular types 10'

    * Si je fais

    re.findall('molecules\s+(\d+)|molecular\s+types(\d+)','molecules 10')

    j'obtiens [('10','')]

    * et si je fais

    re.findall('molecules\s+(\d+)|molecular\s+types(\d+)','molecular types 10')

    j'obtiens [].

    Dans le premier cas je ne comprends pas bien pourquoi il me trouve '' comme solution et dans le deuxième cas je ne comprends pas bien pourquoi il ne trouve rien. Pourtant ma regexp me semble OK.

    Avez-vous une idée ?

    merci beaucoup

    Eric

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 067
    Par défaut
    y a peut-être pas besoin d'utiliser les regex pour des phrases aussi simples,
    Si l'integer recherché se trouve toujours à la fin:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ex = 'molecular types 10'
    ma_val =  int(ex[ex.rfind(' ')+1:])
    print ex ===> 10

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 4
    Par défaut regular expressin
    Merci pour l'info. Mais justement mon problème est que dans le fichier à parser la ligne peut se presenter sous deux formats:

    'molecules 10' ou 'molecular types 10'

    et en plus avec un nombre variables d'espace entre chaque mots. D'où l'utilisation d'une regex.

    Eric

  4. #4
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Peux-tu donner quelques lignes de ton fichier ? Histoire de voir si les regex sont vraiment indispensables.

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 067
    Par défaut
    Citation Envoyé par tontonCalimero Voir le message
    Merci pour l'info. Mais justement mon problème est que dans le fichier à parser la ligne peut se presenter sous deux formats:

    'molecules 10' ou 'molecular types 10'

    et en plus avec un nombre variables d'espace entre chaque mots. D'où l'utilisation d'une regex.

    Eric
    mon exemple fonction quelque soit le nombre d'espaces, le seule condition est que le nombre termine la phrase sans espace après.
    mais bon, comme le dit rambc, fais voir un bout du fichier qu'on se fasse une idée.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 4
    Par défaut regular expression
    Voici quelques lignes du fichiers. Dans ce cas, il contient l'expression

    Automatic FIELD created for 1 molecule of Cumene
    units kJ
    molecules 1 <-- !!! dans un autre fichier cela pourrait être molecular types 1
    Cumene
    nummols 100
    atoms 21
    CB 12.0110 -0.1150 1 0
    CB 12.0110 -0.1150 1 0
    CB 12.0110 -0.1150 1 0
    ...

    merci pour le coup de main

  7. #7
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Voilà des solutions qui marchent (=qui renvoient l'entier 10), avec et sans regex:

    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
     
    print "sans regex"
     
    ch = 'molecules 10'
    print int(ch.split()[-1])
     
    ch = 'molecular types 10'
    print int(ch.split()[-1])
     
    print "avec regex"
     
    import re
     
    motif = r"[+-]?[0-9]+$"
     
    ch = 'molecules 10'
    print int(re.findall(motif, ch)[0])
     
    ch = 'molecular types 10'
    print int(re.findall(motif, ch)[0])
    Tyrtamos

  8. #8
    Membre Expert
    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
    Par défaut group() groups() expressions regulieres
    La RE doit être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    'molecules\s+(\d+)|molecular\s+types\s+(\d+)'



    Je qualifierais le motif que tu cherches de polymorphe: il comporte deux variantes.

    Pour détecter cette polymorphie, la RE totale est RE = RE1|RE2 et chaque REi unitaire comporte la définition d’un groupe, soit deux groupes définis dans la RE totale.

    Même si les deux termes de la RE totale sont exclusifs l’un de l’autre, le renvoi de la fonction comporte, pour chaque chaîne qui a allumé la regex, le compte rendu de ce qu’a trouvé la RE totale, soit les résultats pour les deux groupes définis.





    Remarque:
    findall() et finditer() sont utilisées quand on recherche plusieurs occurences d’un motif dans une chaîne.
    Si ce n’est pas le cas, match() ou search() suffisent.

    Après avoir lu ton dernier post, je pense que findall() n’est pas adaptée.
    match() semble adaptée, à condition que 'molec' soit bien toujours le début de la ligne.
    Mais en fait , pas la peine de se casser la tête; à part des cas particuliers où match() est préférable, il n’y a qu’à mettre search(), et hop !





    Si m = re.search('molecules\s+(\d+)|molecular\s+types\s+(\d+)', ch) existe (c'est a dire qu'il y a matching de la RE dans ch; sinon m vaut None), alors:



    • On obtient ce qui est trouvé par le premier groupe par m.group(1) et ce qui est trouvé par le deuxieme groupe par m.group(2)

      Si on veut tous les groupes, il faut connaître le nombre de groupes définis; ici, 2–> m.group(1,2)

      Noter que quand un groupe ne matche rien dans le motif trouvé, group() exprime le résultat par None, et que ceci ne peut pas être modifié.


    • m.groups() fournit directement un tuple des résultats de matching de tous les groupes définis dans la RE.

      Noter que cette fois, les groupes qui ne matchent avec rien donnent aussi par défaut None, mais qu’on peut spécifier une autre traduction du non-matching d’un groupe en plaçant un argument : m.groups(’rien’), m.groups(o), m.groups("),etc.

      Quant à ce qui est trouvé par chaque groupe, il est obtenu par m.groups()[0] pour le premier groupe, par m.groups()[2] pour le second groupe, etc.
      Remarquer le décalage des indices par rapport à ceux de group().


    • Et m.group(0) alors ?

      C’est la chaîne matchante en totalité, c’est à dire celle exprimée par la RE, qui est plus large que les groupes (habituellement).

      m.group(0) est équivalent à m.group()




    J’ai mis longtemps à comprendre tout ça.
    Après coup, on voit que Python dispose de group() , simple d’emploi, et groups() pour des traitements plus complexes.









    Pour ton problème, ayant défini deux groupes, cela va compliquer l’obtention de l’entier, étant donné qu’il va être soit en position 1 soit en position 2 dans un résultat.

    La RE suivante n’a pas cet inconvénient:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ch = 'il y a molecules 10 fois'
    mu = re.search('molec(?:ules|ular types)\s+(\d+)',ch)
    print mu.groupe(1)

    Explication:
    Pour écrire
    ’ules’ OU ’ular types’ dans une RE, il faut mettre ’|’.

    Mais si on ne limite pas les caractéres concernés par des parenthèses, le OU va s’étendre de part et d’autre jusqu’aux limites de la RE globale.

    On est donc obligé de borner par des parenthèses :
    (ules|ular types)

    Ce faisant on définit un groupe. Le groupe détecteur de l’entier est donc dans ce cas group(2).

    Si on ne veut pas de cette définition superflue du premier groupe, on peut rendre le groupe non capturant au moyen des deux caractéres "?:" placés en tête du groupe.



    PS

    Je ne suis pas un partisan des regex à tout crin.
    La preuve:
    si l’entier est toujours à la fin de la ligne et tout seul, on peut aussi faire simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ch.rpartition(’ ’)[2]

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 4
    Par défaut regular expression
    Merci pour les conseils.

    Malheureusement, mon problème est un peu plus compliqué. Je ne l'ai peut-être pas expliqué assez clairement.

    En fait dans mon fichier, je ne sais pas spécialement à quel moment vont apparaitre les keywords qui m'intéressent ni à quelle position dans la ligne d'ailleurs.

    Je dois donc:
    - parser le fichier ligne par ligne
    - detecter la ligne contenant quelque part molecules 10 OU molecular types 10

    et c'est là où j'en reviens au problème énoncé dans mon premier post.

    Encore merci

    Eric

  10. #10
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Je ne trouve pas ça très compliqué pour Python:

    Si ch = 'molecules 10'
    alors, liste = ch.split() donne ['molecules', '10']

    Si ch = 'molecules type 10'
    alors, liste = ch.split() donne ['molecules', 'type', '10']

    Dans les 2 cas:

    - on peut reconnaitre 'molecules' par un test avec liste[0] qui vaut ici 'molecules'

    - et si oui, retrouver le nombre terminal 10 avec int(liste[-1]) qui vaut ici 10 puisque l'indice -1 veut dire "le dernier".

    S'il n'y a pas d'autres contraintes, les regex ne sont vraiment pas utiles ici.

    Tyrtamos

  11. #11
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 067
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    'molecul' in 'qsdfgfsdwvmoleculardqfdklsfn' ===> true
    franchement, y a pas besoin de regex, amha...

  12. #12
    Membre Expert
    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
    Par défaut
    Sur un fichier de plusieurs Mo répétant des lignes du genre
    faites entrer les molecules 6
    faites sortir les molecular types 22
    il y a molecules 10
    are there molecular types 20
    is there molecular types 34
    il y a molecules 10
    are there molecular types 20
    is there molecular types 34
    histoire de molecules 23
    faites entrer les molecules 6
    faites sortir les molecular types 22
    il y a molecules 10
    are there molecular types 20
    is there molecular types 34
    histoire de molecules 23
    faites entrer les molecules 6
    faites sortir les molecular types 22
    il y a molecules 10
    le code suivant

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    import re
    from time import clock
     
     
    patmol = re.compile('molec(?:ules|ular\s+types)\s+(\d+)')
     
     
    a,b,c,d = [],[],[],[]
    for i in xrange(4):
        f = open('molecul.txt')
        te =clock()
        for ln in f:
            x = patmol.search(ln).group(1)
        tf = clock()
        f.close()
        print tf-te,
        a.append(tf-te)
     
     
        f = open('molecul.txt')
        te =clock()
        for ln in f:
            if 'molecules' in ln or 'molecular tyeps' in ln:
                x = ln[:-1].split()[-1]
        tf = clock()
        f.close()
        print tf-te,
        b.append(tf-te)
     
     
        f = open('molecul.txt')
        te =clock()
        for ln in f:
            x =  ln[ln.rfind('es ')+3:-1]
        tf = clock()
        f.close()
        print tf-te,
        c.append(tf-te)
     
     
        f = open('molecul.txt')
        te =clock()
        for ln in f:
            x = ln[:-1].rpartition(' ')[2]
        tf = clock()
        f.close()
        print tf-te
        d.append(tf-te)
     
    print
    ma = sum(a)/len(a)
    mb = sum(b)/len(b)
    mc = sum(c)/len(c)
    md = sum(d)/len(d)
    print 'regex      ',ma
    print 'split      ',mb,'   ',str(mb/ma*100)[0:5],'% de '+str(ma)
    print 'rfind      ',mc,'   ',str(mc/ma*100)[0:5],'% de '+str(ma)
    print 'rpartition ',md,'   ',str(md/ma*100)[0:5],'% de '+str(ma)
    donne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    regex       1.41694991961
    split       1.07674271451     75.99 % de 1.41694991961
    rfind       0.636681337991     44.93 % de 1.41694991961
    rpartition  0.482137045351     34.02 % de 1.41694991961
    Je n'aurais pas cru que rpartition() soit la meilleure solution, et que la regex soit aussi lente.
    Une regex permet plus de contrôle , cependant.

  13. #13
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 050
    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 : 4 050
    Par défaut
    Je ne suis pas surpris par la regex, mais plus par le split. Comme quoi avec python on a des surprises.


Discussions similaires

  1. Regular expression qui ne fonctionne pas
    Par Remedy dans le forum Langage
    Réponses: 2
    Dernier message: 11/05/2007, 16h52
  2. [Regular expression] Possessive quantifiers
    Par Pragmateek dans le forum Langage
    Réponses: 1
    Dernier message: 24/06/2006, 12h55
  3. [debutant] Regular Expression
    Par absolut75 dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 13/06/2006, 01h43
  4. [RegEx] Empty regular expression
    Par Khrysby dans le forum Langage
    Réponses: 2
    Dernier message: 24/04/2006, 22h25
  5. [Regular Expressions] Numérotation romaine
    Par ramalho dans le forum Valider
    Réponses: 3
    Dernier message: 24/02/2004, 17h43

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