Comment utiliser le module d’expression régulière Python re (match, search, sub, etc.)

Affaires

Pour effectuer le traitement des expressions régulières en Python, nous utilisons le module re de la bibliothèque standard. Il vous permet d'extraire, de remplacer et de diviser des chaînes de caractères à l'aide de motifs d'expression régulière.

Dans cette section, nous allons d'abord expliquer les fonctions et les méthodes du module re.

  • Compilation de modèles d'expressions régulières :compile()
  • objet du match
  • Vérifier si le début de la chaîne correspond, extraire :match()
  • Vérifiez si les correspondances ne se limitent pas au début :search()
  • Vérifiez si la chaîne entière correspond :fullmatch()
  • Obtenez une liste de toutes les pièces correspondantes :findall()
  • Obtenir toutes les parties correspondantes sous forme d'itérateur :finditer()
  • Remplacez la pièce correspondante :sub(),subn()
  • Séparation de chaînes de caractères avec des modèles d'expression régulière :split()

Après cela, j'expliquerai les méta-caractères (caractères spéciaux) et les séquences spéciales des expressions régulières qui peuvent être utilisées dans le module re. En gros, il s'agit de la syntaxe standard des expressions régulières, mais il faut faire attention à la définition des drapeaux (notamment re.ASCII).

  • Métacaractères d'expression régulière, séquences spéciales et avertissements en Python
  • Mise en place du drapeau
    • Limité aux caractères ASCII :re.ASCII
    • Non sensible à la casse :re.IGNORECASE
    • Faites correspondre le début et la fin de chaque ligne :re.MULTILINE
    • Spécifier plusieurs drapeaux
  • Matchs avides et non avides

Compiler le modèle d'expression régulière : compile()

Il existe deux façons d'effectuer le traitement des expressions régulières dans le module re.

Fonctionnement

Le premier est une fonction.re.match(),re.sub()Des fonctions comme celles-ci sont disponibles pour effectuer des extractions, des remplacements et d'autres traitements à l'aide de modèles d'expressions régulières.

Les détails des fonctions seront décrits plus tard, mais dans toutes les fonctions, le premier argument est la chaîne du motif d'expression régulière, suivie de la chaîne à traiter et ainsi de suite. Par exemple, dans re.sub(), qui effectue une substitution, le deuxième argument est la chaîne de substitution, et le troisième argument est la chaîne à traiter.

import re

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.match(r'([a-z]+)@([a-z]+)\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

result = re.sub(r'([a-z]+)@([a-z]+)\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

Notez que [a-z] dans le modèle d'expression régulière de cet exemple signifie tout caractère de a à z (c'est-à-dire l'alphabet minuscule), et que + signifie répéter le modèle précédent (dans ce cas [a-z]) une ou plusieurs fois. Le [a-z]+ correspond à toute chaîne qui répète un ou plusieurs caractères alphabétiques minuscules.

. est un méta-caractère (un caractère ayant une signification spéciale) et doit être échappé par une barre oblique inversée.

Étant donné que les chaînes de motifs d'expressions régulières utilisent souvent de nombreux antislashs, il est pratique d'utiliser des chaînes brutes comme dans l'exemple.

Exécution d'une méthode d'un objet motif d'expression régulière

La deuxième façon de traiter les expressions régulières dans le module re est la méthode de l'objet motif d'expression régulière.

À l'aide de re.compile(), vous pouvez compiler une chaîne de motifs d'expression régulière pour créer un objet de motif d'expression régulière.

p = re.compile(r'([a-z]+)@([a-z]+)\.com')

print(p)
# re.compile('([a-z]+)@([a-z]+)\\.com')

print(type(p))
# <class 're.Pattern'>

re.match(),re.sub()Par exemple, le même processus que ces fonctions peut être exécuté en tant que méthodes match(),sub() des objets d'expression régulière.

m = p.match(s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

result = p.sub('new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

Toutes les fonctions re.xxx() décrites ci-dessous sont également fournies en tant que méthodes de l'objet expression régulière.

Si vous répétez un processus qui utilise le même motif, il est plus efficace de générer un objet d'expression régulière avec re.compile() et de l'utiliser partout.

Dans l'exemple de code suivant, la fonction est utilisée sans compilation pour des raisons de commodité, mais si vous souhaitez utiliser le même motif de manière répétée, il est recommandé de la compiler à l'avance et de l'exécuter en tant que méthode d'un objet d'expression régulière.

objet du match

match(), search(), etc. retournent un objet de correspondance.

s = 'aaa@xxx.com'

m = re.match(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(type(m))
# <class 're.Match'>

La chaîne et la position correspondantes sont obtenues à l'aide des méthodes suivantes de l'objet match.

  • Obtenez l'emplacement du match :start(),end(),span()
  • Obtenez la chaîne de caractères correspondante :group()
  • Obtenez la chaîne de caractères pour chaque groupe :groups()
print(m.start())
# 0

print(m.end())
# 11

print(m.span())
# (0, 11)

print(m.group())
# aaa@xxx.com

Si vous enfermez une partie d'un motif d'expression régulière dans une chaîne de caractères avec des parenthèses(), la partie sera traitée comme un groupe. Dans ce cas, la chaîne de la partie qui correspond à chaque groupe dans groups() peut être obtenue sous forme de tuple.

m = re.match(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(m.groups())
# ('aaa', 'xxx', 'com')

Vérifie si le début d'une chaîne de caractères correspond, extrait : match()

match() renvoie un objet match si le début de la chaîne correspond au motif.

Comme mentionné ci-dessus, l'objet match peut être utilisé pour extraire la sous-chaîne correspondante, ou simplement pour vérifier si une correspondance a été faite.

match() ne vérifie que le début. S'il n'y a pas de chaîne correspondante au début, elle renvoie None.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.match(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

m = re.match(r'[a-z]+@[a-z]+\.net', s)
print(m)
# None

Recherche de correspondances non limitées au début, extrait : search()

Comme match(), il retourne un objet match s'il y a correspondance.

S'il y a plusieurs parties correspondantes, seule la première partie correspondante sera renvoyée.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.search(r'[a-z]+@[a-z]+\.net', s)
print(m)
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

m = re.search(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

Si vous voulez obtenir toutes les parties correspondantes, utilisez findall() ou finditer() comme décrit ci-dessous.

Vérifier si la chaîne entière correspond : fullmatch()

Pour vérifier si la chaîne entière correspond au motif de l'expression régulière, utilisez fullmatch(). Ceci est utile, par exemple, pour vérifier si une chaîne est valide ou non en tant qu'adresse électronique.

Si la chaîne entière correspond, un objet match est renvoyé.

s = 'aaa@xxx.com'

m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

S'il y a des parties non correspondantes (seulement des correspondances partielles ou pas de correspondance du tout), None est retourné.

s = '!!!aaa@xxx.com!!!'

m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# None

La fonction fullmatch() a été ajoutée dans Python 3.4. Si vous voulez faire la même chose dans les versions antérieures, utilisez match() et un métacaractère correspondant $ à la fin. Si la chaîne entière, du début à la fin, ne correspond pas, elle renvoie None.

s = '!!!aaa@xxx.com!!!'

m = re.match(r'[a-z]+@[a-z]+\.com$', s)
print(m)
# None

Obtenir une liste de toutes les parties correspondantes : findall()

findall() retourne une liste de toutes les sous-chaînes correspondantes. Notez que les éléments de la liste ne sont pas des objets match mais des chaînes de caractères.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.findall(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# ['aaa@xxx.com', 'bbb@yyy.com', 'ccc@zzz.net']

Le nombre de parties correspondantes peut être vérifié à l'aide de la fonction intégrée len(), qui renvoie le nombre d'éléments de la liste.

print(len(result))
# 3

Le regroupement avec des parenthèses() dans un motif d'expression régulière renvoie une liste de tuples dont les éléments sont les chaînes de caractères de chaque groupe. Ceci est équivalent à groups() dans l'objet match.

result = re.findall(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(result)
# [('aaa', 'xxx', 'com'), ('bbb', 'yyy', 'com'), ('ccc', 'zzz', 'net')]

Les parenthèses de groupe () peuvent être imbriquées. Ainsi, si vous souhaitez également obtenir l'ensemble de la correspondance, il vous suffit de la mettre entre parenthèses ().

result = re.findall(r'(([a-z]+)@([a-z]+)\.([a-z]+))', s)
print(result)
# [('aaa@xxx.com', 'aaa', 'xxx', 'com'), ('bbb@yyy.com', 'bbb', 'yyy', 'com'), ('ccc@zzz.net', 'ccc', 'zzz', 'net')]

Si aucune correspondance n'est trouvée, un tuple vide est renvoyé.

result = re.findall('[0-9]+', s)
print(result)
# []

Récupérer toutes les parties correspondantes sous forme d'itérateur : finditer()

finditer() retourne toutes les parties correspondantes sous forme d'itérateur. Les éléments ne sont pas des chaînes de caractères comme findall(), mais des objets de correspondance, de sorte que vous pouvez obtenir la position (index) des parties correspondantes.

L'itérateur lui-même ne peut pas être imprimé avec print() pour obtenir son contenu. Si vous utilisez la fonction intégrée next() ou l'instruction for, vous pouvez obtenir les contenus un par un.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# <callable_iterator object at 0x10b0efa90>

print(type(result))
# <class 'callable_iterator'>

for m in result:
    print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

Il peut également être converti en liste avec list().

l = list(re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s))
print(l)
# [<re.Match object; span=(0, 11), match='aaa@xxx.com'>, <re.Match object; span=(13, 24), match='bbb@yyy.com'>, <re.Match object; span=(26, 37), match='ccc@zzz.net'>]

print(l[0])
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(type(l[0]))
# <class 're.Match'>

print(l[0].span())
# (0, 11)

Si vous voulez obtenir la position de toutes les parties correspondantes, la notation de compréhension de liste est plus pratique que list().

print([m.span() for m in re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)])
# [(0, 11), (13, 24), (26, 37)]

L'itérateur extrait les éléments dans l'ordre. Notez que si vous essayez d'extraire d'autres éléments après avoir atteint la fin, il ne vous restera rien.

result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)

for m in result:
    print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

print(list(result))
# []

Remplacer les parties correspondantes : sub(), subn()

En utilisant sub(), vous pouvez remplacer la partie correspondante par une autre chaîne. La chaîne substituée sera retournée.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

print(type(result))
# <class 'str'>

Lors d'un regroupement avec des parenthèses(), la chaîne trouvée peut être utilisée dans la chaîne remplacée.

Par défaut, les éléments suivants sont pris en charge : Notez que pour les chaînes normales qui ne sont pas des chaînes brutes, une barre oblique inverse doit être listée avant la barre oblique inverse pour échapper à la barre oblique inverse.

\1La première parenthèse
\2La deuxième parenthèse
\3La troisième parenthèse
result = re.sub(r'([a-z]+)@([a-z]+)\.com', r'\1@\2.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net

?P<xxx>
Si vous nommez le groupe en l'écrivant au début des parenthèses du modèle d'expression régulière, vous pouvez le spécifier en utilisant le nom au lieu du numéro, comme illustré ci-dessous.
\g<xxx>

result = re.sub(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net

L'argument count spécifie le nombre maximum de remplacements. Seul le compte du côté gauche sera remplacé.

result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# new-address, bbb@yyy.com, ccc@zzz.net

subn() renvoie un tuple de la chaîne substituée (identique à la valeur de retour de sub()) et du nombre de parties substituées (le nombre qui correspond au motif).

result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# ('new-address, new-address, ccc@zzz.net', 2)

La méthode pour spécifier les arguments est la même que pour sub(). Vous pouvez utiliser la partie groupée par des parenthèses, ou spécifier le nombre d'arguments.

result = re.subn(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# ('aaa@xxx.net, bbb@yyy.net, ccc@zzz.net', 2)

result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# ('new-address, bbb@yyy.com, ccc@zzz.net', 1)

Séparation de chaînes de caractères avec des motifs d'expression régulière : split()

split() divise la chaîne de caractères à la partie qui correspond au motif, et la renvoie sous forme de liste.

Notez que la première et la dernière correspondance contiendront des chaînes vides au début et à la fin de la liste résultante.

s = '111aaa222bbb333'

result = re.split('[a-z]+', s)
print(result)
# ['111', '222', '333']

result = re.split('[0-9]+', s)
print(result)
# ['', 'aaa', 'bbb', '']

L'argument maxsplit spécifie le nombre maximum de fractionnements (morceaux). Seul le compte du côté gauche sera divisé.

result = re.split('[a-z]+', s, 1)
print(result)
# ['111', '222bbb333']

Métacaractères d'expression régulière, séquences spéciales et avertissements en Python

Les principaux métacaractères (caractères spéciaux) et séquences spéciales des expressions régulières qui peuvent être utilisés dans le module Python 3 re sont les suivants

métacaractèrecontenu
.Tout caractère unique autre qu'une nouvelle ligne (y compris une nouvelle ligne avec l'indicateur DOTALL).
^Le début de la chaîne (correspond également au début de chaque ligne avec l'indicateur MULTILINE)
$La fin de la chaîne (correspond également à la fin de chaque ligne avec l'indicateur MULTILINE)
*Répéter le motif précédent plus de 0 fois
+Répétez le motif précédent au moins une fois.
?Répéter le motif précédent 0 ou 1 fois
{m}Répétez le motif précédent m fois
{m, n}Le dernier modèle.m~nrépéter
[]Un ensemble de caractères[]Correspond à l'un de ces caractères
|OUA|BCorrespond au modèle A ou B
séquence spécialecontenu
\dnombres décimaux Unicode (limités aux nombres ASCII par le drapeau ASCII)
\D\dC'est-à-dire le contraire de ça.
\scaractères d'espacement Unicode (limités aux caractères d'espacement ASCII par le drapeau ASCII)
\S\sC'est-à-dire le contraire de ça.
\wCaractères de mot et caractères de soulignement Unicode (limités aux caractères alphanumériques et aux caractères de soulignement ASCII par le drapeau ASCII)
\W\wC'est-à-dire le contraire de ça.

Ils ne sont pas tous répertoriés dans ce tableau. Consultez la documentation officielle pour une liste complète.

Notez également que certaines des significations sont différentes dans Python 2.

Mise en place du drapeau

Comme le montre le tableau ci-dessus, certains métacaractères et séquences spéciales changent de mode en fonction du drapeau.

Seuls les principaux drapeaux sont couverts ici. Voir la documentation officielle pour le reste.

Limité aux caractères ASCII : re.ASCII

\wCela correspondra également aux kanji à double octet, aux caractères alphanumériques, etc. par défaut pour les chaînes Python 3. Elle n'est pas équivalente à ce qui suit car il ne s'agit pas d'une expression régulière standard.[a-zA-Z0-9_]

m = re.match(r'\w+', '漢字ABC123')
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>

m = re.match('[a-zA-Z0-9_]+', '漢字ABC123')
print(m)
# None

Si vous spécifiez re.ASCII pour les drapeaux d'argument dans chaque fonction, ou si vous ajoutez le drapeau en ligne suivant au début de la chaîne de motifs de l'expression régulière, celle-ci ne correspondra qu'aux caractères ASCII (elle ne correspondra pas aux caractères japonais à double octet, aux caractères alphanumériques, etc.)
(?a)
Dans ce cas, les deux suivantes sont équivalentes.
\w=[a-zA-Z0-9_]

m = re.match(r'\w+', '漢字ABC123', flags=re.ASCII)
print(m)
# None

m = re.match(r'(?a)\w+', '漢字ABC123')
print(m)
# None

Il en va de même lors de la compilation avec re.compile(). Utilisez l'argument flags ou inline flags.

p = re.compile(r'\w+', flags=re.ASCII)
print(p)
# re.compile('\\w+', re.ASCII)

print(p.match('漢字ABC123'))
# None

p = re.compile(r'(?a)\w+')
print(p)
# re.compile('(?a)\\w+', re.ASCII)

print(p.match('漢字ABC123'))
# None

ASCII est également disponible sous la forme courte re. A. Vous pouvez utiliser l'un ou l'autre.

print(re.ASCII is re.A)
# True

\W, l'opposé de \W, est également affecté par re.ASCII et les drapeaux inline.

m = re.match(r'\W+', '漢字ABC123')
print(m)
# None

m = re.match(r'\W+', '漢字ABC123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>

Comme pour \w, les deux suivantes correspondent par défaut aux caractères à un et à deux octets, mais sont limitées aux caractères à un octet si re.ASCII ou des drapeaux en ligne sont spécifiés.

  • Faites correspondre les chiffres\d
  • Correspond à un espace vide\s
  • Correspond aux non-nombres\D
  • Correspond à tout élément non spatial.\S
m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# None

m = re.match(r'\s+', ' ')  # full-width space
print(m)
# <re.Match object; span=(0, 1), match='\u3000'>

m = re.match(r'\s+', ' ', flags=re.ASCII)
print(m)
# None

Non sensible à la casse :re.IGNORECASE

Par défaut, il est sensible à la casse. Pour faire correspondre les deux, vous devez inclure les lettres majuscules et minuscules dans le motif.

re.IGNORECASESi cette option est spécifiée, la correspondance se fera sans tenir compte de la casse. Équivalent de l'indicateur i dans les expressions régulières standard.

m = re.match('[a-zA-Z]+', 'abcABC')
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

m = re.match('[a-z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

m = re.match('[A-Z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

Vous pouvez utiliser “moins de” ou “égal à”.

  • drapeau en ligne(?i)
  • abréviationre.I

Faites correspondre le début et la fin de chaque ligne :re.MULTILINE

^Les métacaractères de cette expression régulière correspondent au début de la chaîne.

Par défaut, seul le début de la chaîne entière est pris en compte, mais la commande suivante prendra en compte le début de chaque ligne également. Équivalent de l'indicateur m dans les expressions régulières standard.
re.MULTILINE

s = '''aaa-xxx
bbb-yyy
ccc-zzz'''

print(s)
# aaa-xxx
# bbb-yyy
# ccc-zzz

result = re.findall('[a-z]+', s)
print(result)
# ['aaa', 'xxx', 'bbb', 'yyy', 'ccc', 'zzz']

result = re.findall('^[a-z]+', s)
print(result)
# ['aaa']

result = re.findall('^[a-z]+', s, flags=re.MULTILINE)
print(result)
# ['aaa', 'bbb', 'ccc']

$Correspond à la fin de la chaîne de caractères. Par défaut, seule la fin de la chaîne entière est prise en compte.
re.MULTILINESi vous le spécifiez, il correspondra également à la fin de chaque ligne.

result = re.findall('[a-z]+$', s)
print(result)
# ['zzz']

result = re.findall('[a-z]+$', s, flags=re.MULTILINE)
print(result)
# ['xxx', 'yyy', 'zzz']

Vous pouvez utiliser “moins de” ou “égal à”.

  • drapeau en ligne(?m)
  • abréviationre.M

Spécifier plusieurs drapeaux

|Si vous voulez activer plusieurs drapeaux en même temps, utilisez ceci. Dans le cas des drapeaux en ligne, chaque caractère doit être suivi d'une lettre, comme indiqué ci-dessous.
(?am)

s = '''aaa-xxx
漢漢漢-字字字
bbb-zzz'''

print(s)
# aaa-xxx
# 漢漢漢-字字字
# bbb-zzz

result = re.findall(r'^\w+', s, flags=re.M)
print(result)
# ['aaa', '漢漢漢', 'bbb']

result = re.findall(r'^\w+', s, flags=re.M | re.A)
print(result)
# ['aaa', 'bbb']

result = re.findall(r'(?am)^\w+', s)
print(result)
# ['aaa', 'bbb']

Matchs avides et non avides

Il s'agit d'un problème général avec les expressions régulières, pas seulement un problème avec Python, mais je vais écrire à ce sujet parce qu'il a tendance à me causer des problèmes.

Par défaut, il s'agit d'une correspondance gourmande, qui correspond à la chaîne la plus longue possible.

  • *
  • +
  • ?
s = 'aaa@xxx.com, bbb@yyy.com'

m = re.match(r'.+com', s)
print(m)
# <re.Match object; span=(0, 24), match='aaa@xxx.com, bbb@yyy.com'>

print(m.group())
# aaa@xxx.com, bbb@yyy.com

Le ? qui le suit donnera lieu à une correspondance minimale non avide, correspondant à la chaîne la plus courte possible.

  • *?
  • +?
  • ??
m = re.match(r'.+?com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(m.group())
# aaa@xxx.com

Notez que la correspondance avide par défaut peut correspondre à des chaînes de caractères inattendues.

Copied title and URL