Existe-t-il un moyen dans Python pour accéder aux groupes de correspondance sans créer explicitement un objet de correspondance (ou une autre façon d'embellir l'exemple ci-dessous)?
Voici un exemple pour clarifier ma motivation pour la question:
Code Perl suivant
if ($statement =~ /I love (\w+)/) {
print "He loves $1\n";
}
elsif ($statement =~ /Ich liebe (\w+)/) {
print "Er liebt $1\n";
}
elsif ($statement =~ /Je t\'aime (\w+)/) {
print "Il aime $1\n";
}
traduit en Python
m = re.search("I love (\w+)", statement)
if m:
print "He loves",m.group(1)
else:
m = re.search("Ich liebe (\w+)", statement)
if m:
print "Er liebt",m.group(1)
else:
m = re.search("Je t'aime (\w+)", statement)
if m:
print "Il aime",m.group(1)
semble très maladroit (if-else-cascade, correspond à la création d'objet).
Vous pouvez créer une petite classe qui renvoie le résultat booléen de l'appel de match, et conserve les groupes correspondants pour une récupération ultérieure:
import re
class REMatcher(object):
def __init__(self, matchstring):
self.matchstring = matchstring
def match(self,regexp):
self.rematch = re.match(regexp, self.matchstring)
return bool(self.rematch)
def group(self,i):
return self.rematch.group(i)
for statement in ("I love Mary",
"Ich liebe Margot",
"Je t'aime Marie",
"Te amo Maria"):
m = REMatcher(statement)
if m.match(r"I love (\w+)"):
print "He loves",m.group(1)
Elif m.match(r"Ich liebe (\w+)"):
print "Er liebt",m.group(1)
Elif m.match(r"Je t'aime (\w+)"):
print "Il aime",m.group(1)
else:
print "???"
Moins efficace, mais plus simple:
m0 = re.match("I love (\w+)", statement)
m1 = re.match("Ich liebe (\w+)", statement)
m2 = re.match("Je t'aime (\w+)", statement)
if m0:
print "He loves",m0.group(1)
Elif m1:
print "Er liebt",m1.group(1)
Elif m2:
print "Il aime",m2.group(1)
Le problème avec le truc Perl est la mise à jour implicite de certaines variables cachées. C'est tout simplement difficile à réaliser dans Python car vous devez avoir une instruction d'affectation pour mettre à jour réellement toutes les variables.
La version avec moins de répétition (et une meilleure efficacité) est la suivante:
pats = [
("I love (\w+)", "He Loves {0}" ),
("Ich liebe (\w+)", "Er Liebe {0}" ),
("Je t'aime (\w+)", "Il aime {0}")
]
for p1, p3 in pats:
m= re.match( p1, statement )
if m:
print p3.format( m.group(1) )
break
Une variation mineure que certains folkloriques Perl préfèrent:
pats = {
"I love (\w+)" : "He Loves {0}",
"Ich liebe (\w+)" : "Er Liebe {0}",
"Je t'aime (\w+)" : "Il aime {0}",
}
for p1 in pats:
m= re.match( p1, statement )
if m:
print pats[p1].format( m.group(1) )
break
Cela ne vaut guère la peine d'être mentionné, sauf que cela vient parfois des programmeurs Perl.
ce n'est pas une solution regex.
alist={"I love ":""He loves"","Je t'aime ":"Il aime","Ich liebe ":"Er liebt"}
for k in alist.keys():
if k in statement:
print alist[k],statement.split(k)[1:]
Vous pouvez créer une fonction d'assistance:
def re_match_group(pattern, str, out_groups):
del out_groups[:]
result = re.match(pattern, str)
if result:
out_groups[:len(result.groups())] = result.groups()
return result
Et puis utilisez-le comme ceci:
groups = []
if re_match_group("I love (\w+)", statement, groups):
print "He loves", groups[0]
Elif re_match_group("Ich liebe (\w+)", statement, groups):
print "Er liebt", groups[0]
Elif re_match_group("Je t'aime (\w+)", statement, groups):
print "Il aime", groups[0]
C'est un peu maladroit, mais ça fait le travail.
À partir de Python 3.8
Et de l'introduction de expressions d'affectation (PEP 572) (opérateur :=
), Nous pouvons maintenant capturer la valeur de condition re.search(pattern, statement)
dans une variable (disons tout match
) afin de vérifier si ce n'est pas None
puis de la réutiliser dans le corps de la condition:
if match := re.search('I love (\w+)', statement):
print(f'He loves {match.group(1)}')
Elif match := re.search("Ich liebe (\w+)", statement):
print(f'Er liebt {match.group(1)}')
Elif match := re.search("Je t'aime (\w+)", statement):
print(f'Il aime {match.group(1)}')