group() groups() expressions regulieres
La RE doit être
Code:
'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:
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:
ch.rpartition( )[2]