Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Expression régulière

5 réponses
Avatar
Thoma
Bonsoir,

J'ai découvert les expressions régulières récemment.

Aujourd'hui, j'essaye de les utiliser pour extraire deux champs :

Les deux lignes suivantes sont :

test?champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4=valeur4
test?champ1=valeur1&champ2=valeur2&champ4=valeur4

et je veux extraire "valeur1" et "valeur2".

J'ai crée l'expression suivante :

champ1=(.*)&champ2=(.*)&

Résultat : je récupère bien "valeur1". Tout se complique avec le second
groupe puisque je me retrouve avec "valeur2&champ3=valeur3". Je
m'attendais à n'avoir que "valeur2".

En cherchant sur la toile, j'ai trouvé une histoire de 'greedy' et
'ungreedy'.

Malheureusement, mes essais ne m'ont pas permis de trouver la bonne
expression me permettant d'extraire "valeur1" et "valeur2".

Si quelqu'un a une idée (et surtout une explication), je suis preneur.

D'avance merci

Thoma

5 réponses

Avatar
bruno.desthuilliers
On 28 jan, 21:42, Thoma wrote:
Bonsoir,

J'ai découvert les expressions régulières récemment.

Aujourd'hui, j'essaye de les utiliser pour extraire deux champs :

Les deux lignes suivantes sont :

test?champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4=valeur4
test?champ1=valeur1&champ2=valeur2&champ4=valeur4


C'est une requête http GET, ça. Il y a un module dans la stdlib qui
sait les gérer.

et je veux extraire "valeur1" et "valeur2".

J'ai crée l'expression suivante :

champ1=(.*)&champ2=(.*)&

Résultat : je récupère bien "valeur1". Tout se complique avec le sec ond
groupe puisque je me retrouve avec "valeur2&champ3=valeur3". Je
m'attendais à n'avoir que "valeur2".

En cherchant sur la toile, j'ai trouvé une histoire de 'greedy' et
'ungreedy'.

Malheureusement, mes essais ne m'ont pas permis de trouver la bonne
expression me permettant d'extraire "valeur1" et "valeur2".


s = "test?champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4=vale ur4"
m = re.search(r"champ1=(.*)&champ2=(.*?)&", s)
print m.groups()

Si quelqu'un a une idée (et surtout une explication), je suis preneur.


Par défaut, une expression rationnelle essaie de "consommer" le plus
possible de caractères correspondants (d'où le terme 'greedy', ie
'avide'). Dans ton cas, après "champ2=", elle prend tout ce qu'elle
peut, c'est à dire jusqu'au dernier '&' - celui qui est avant
'champ4'. Le modifiuer 'non-greedy' inverse ce comportement, et donne
le résultat attendu. Pour le premier groupe capturant (champ1), le
problème ne se pose pas puisque tu a '&champ2=' juste derrière.

Note que dans le cas présent, tu aurais aussi pu utiliser une classe
complémentée, ie:

r"champ1=(.*)&champ2=([^&]*)"

"[^&]" signifiant "tout sauf &"

Note aussi que les expressions rationnelles ne sont pas forcément la
bonne solution. Dans l'absolu, puisque c'est une requête HTTP, autant
utiliser le module qui va bien (regarde du côté de cgi). A défaut, ç a
se règle aussi très aisément à coup de split:

s = "test?champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4= valeur4"
s1 = s.split("?")[1]
s1
'champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4=valeur4'



s2 = s1.split('&')
s2
['champ1=valeur1', 'champ2=valeur2', 'champ3=valeur3',



'champ4=valeur4']
d = dict(tuple(p.split('=')) for p in s2)
print d
{'champ4': 'valeur4', 'champ1': 'valeur1', 'champ3': 'valeur3',



'champ2': 'valeur2'}



Avatar
kib
Salut,

sinon, tu peux toujours utiliser des groupes nommés, c'est bien pratique
(ici, valeur est définie comme étant tout ce qui se trouve entre "=" et
le prochain "&", càd qu'elle n'est pas greedy (gourmande), d'où le point
d'interrogation dans '.*?').

#-----------------------------------------------------------------
import re

test = """test?champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4=valeur4
test?champ1=valeur1&champ2=valeur2&champ4=valeur4
"""

rech = re.compile(r"champ[12][=](?P<valeur>.*?)&")

for el in rech.finditer(test) :
print el.group('valeur')
#-----------------------------------------------------------------

Je te conseille d'utilise kodos pour les regexps, c'est un très bon outil.
Avatar
Méta-MCI \(MVP\)
Bonsoir !

Je me pose une question (tordue ?) :
Champ1 peut-il contenir la valeur suivante :
&champ2=x&
?

Bon, Ok ; exit()...

Michel Claveau
Avatar
Bruno Desthuilliers
Bonsoir !
Je me pose une question (tordue ?) : Champ1 peut-il contenir la valeur
suivante : &champ2=x&
?


Si la chaine est une requête HTTP (avoue que ça y ressemble beaucoup
!-), ce n'est pas possible. Par contre, tu peux avoir:

champ2=valeur1&champ2=valeur2&champ2=valeur3

Avatar
Thoma
Bonsoir,

J'ai découvert les expressions régulières récemment.

Aujourd'hui, j'essaye de les utiliser pour extraire deux champs :

Les deux lignes suivantes sont :

test?champ1=valeur1&champ2=valeur2&champ3=valeur3&champ4=valeur4
test?champ1=valeur1&champ2=valeur2&champ4=valeur4

et je veux extraire "valeur1" et "valeur2".

J'ai crée l'expression suivante :

champ1=(.*)&champ2=(.*)&

Résultat : je récupère bien "valeur1". Tout se complique avec le second
groupe puisque je me retrouve avec "valeur2&champ3=valeur3". Je
m'attendais à n'avoir que "valeur2".

En cherchant sur la toile, j'ai trouvé une histoire de 'greedy' et
'ungreedy'.

Malheureusement, mes essais ne m'ont pas permis de trouver la bonne
expression me permettant d'extraire "valeur1" et "valeur2".

Si quelqu'un a une idée (et surtout une explication), je suis preneur.

D'avance merci

Thoma


Bonsoir,

Je vous remerci tous de l'aide que vous m'avez apporté.
Maintenant, je comprends l'utilisation du ungreedy (je le plaçais au
mauvais endroit lors de mes multiples essais).

Thoma