Cum se utilizează modulul de expresii regulate Python re (match, search, sub, etc.)

Afaceri

Pentru a efectua procesarea expresiilor regulate în Python, folosim modulul re din biblioteca standard. Acesta vă permite să extrageți, să înlocuiți și să divizați șiruri de caractere folosind modele de expresii regulate.

În această secțiune, vom explica mai întâi funcțiile și metodele modulului re.

  • Compilarea modelelor de expresii regulate:compile()
  • obiect de potrivire
  • Verifică dacă începutul șirului se potrivește, extrage:match()
  • Verificați dacă există meciuri care nu se limitează la început:search()
  • Verifică dacă întregul șir se potrivește:fullmatch()
  • Obțineți o listă cu toate piesele care se potrivesc:findall()
  • Obține toate părțile care se potrivesc sub forma unui iterator:finditer()
  • Înlocuiți piesa corespunzătoare:sub(),subn()
  • Divizarea șirurilor de caractere cu modele de expresii regulate:split()

După aceea, voi explica metacaracterele (caractere speciale) și secvențele speciale ale expresiilor regulate care pot fi utilizate în modulul re. Practic, este vorba de sintaxa standard a expresiilor regulate, dar aveți grijă la setarea indicatoarelor (în special re.ASCII).

  • Metacaracterele expresiilor regulate, secvențe speciale și avertismente în Python
  • Setarea steagului
    • Limitat la caractere ASCII:re.ASCII
    • Nu ține cont de majuscule și minuscule:re.IGNORECASE
    • Potriviți începutul și sfârșitul fiecărui rând:re.MULTILINE
    • Specificați mai multe steaguri
  • Meciuri cu și fără lăcomie

Compilarea modelului de expresie regulată: compile()

Există două moduri de a efectua procesarea expresiilor regulate în modulul re.

Rulați cu funcția

Prima este o funcție.re.match(),re.sub()Funcțiile de acest tip sunt disponibile pentru a efectua extragerea, înlocuirea și alte procese care utilizează modele de expresii regulate.

Detaliile funcțiilor vor fi descrise mai târziu, dar în toate funcțiile, primul argument este șirul de caractere al expresiei regulate, urmat de șirul de caractere care urmează să fie procesat și așa mai departe. De exemplu, în re.sub(), care efectuează o substituție, al doilea argument este șirul de substituție, iar al treilea argument este șirul care urmează să fie procesat.

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

Rețineți că [a-z] în modelul de expresie regulată din acest exemplu înseamnă orice caracter de la a la z (adică alfabetul minuscul), iar + înseamnă repetarea modelului anterior (în acest caz [a-z]) de una sau mai multe ori. [a-z]+ se potrivește cu orice șir de caractere care repetă unul sau mai multe caractere alfabetice minuscule.

. este un metacaracter (un caracter cu semnificație specială) și trebuie evadat cu o backslash.

Deoarece șirurile de modele de expresii regulate folosesc adesea o mulțime de backslash-uri, este convenabil să se utilizeze șiruri brute, ca în exemplul de mai jos.

Se execută într-o metodă a unui obiect model de expresie regulată

A doua modalitate de procesare a expresiilor regulate în modulul re este metoda obiectului model de expresie regulată.

Folosind re.compile(), puteți compila un șir de modele de expresii regulate pentru a crea un obiect de model de expresie regulată.

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()De exemplu, același proces ca și aceste funcții poate fi executat ca metode match(),sub() ale obiectelor de expresii regulate.

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

Toate funcțiile re.xxx() descrise mai jos sunt, de asemenea, furnizate ca metode ale obiectului expresie regulată.

Dacă repetați un proces care utilizează același model, este mai eficient să generați un obiect de expresie regulată cu re.compile() și să îl utilizați în continuare.

În exemplul de cod de mai jos, funcția este utilizată fără compilare pentru comoditate, dar dacă doriți să utilizați același model în mod repetat, se recomandă să o compilați în prealabil și să o executați ca metodă a unui obiect de expresie regulată.

obiect de potrivire

match(), search(), etc. returnează un obiect match.

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'>

Șirul de caractere și poziția corespunzătoare sunt obținute cu ajutorul următoarelor metode ale obiectului match.

  • Obține locația meciului:start(),end(),span()
  • Obține șirul care se potrivește:group()
  • Obține șirul pentru fiecare grup:groups()
print(m.start())
# 0

print(m.end())
# 11

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

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

Dacă includeți o parte a unui model de expresie regulată într-un șir de caractere cu paranteze(), partea respectivă va fi procesată ca un grup. În acest caz, șirul de caractere al părții care se potrivește cu fiecare grup din groups() poate fi obținut sub formă 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')

Verifică dacă începutul unui șir de caractere se potrivește, extrage: match()

match() returnează un obiect match dacă începutul șirului se potrivește cu modelul.

După cum s-a menționat mai sus, obiectul match poate fi utilizat pentru a extrage subșirul corespunzător sau pur și simplu pentru a verifica dacă s-a realizat o potrivire.

match() va verifica doar începutul. În cazul în care nu există un șir de caractere care să corespundă la început, se returnează 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

Verifică dacă există corespondențe care nu se limitează la început, extrage: search()

Ca și match(), returnează un obiect match dacă se potrivește.

În cazul în care există mai multe părți care se potrivesc, va fi returnată numai prima parte care se potrivește.

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'>

Dacă doriți să obțineți toate părțile care corespund, utilizați findall() sau finditer(), după cum se descrie mai jos.

Verifică dacă întregul șir se potrivește: fullmatch()

Pentru a verifica dacă întregul șir de caractere se potrivește cu modelul expresiei regulate, utilizați fullmatch(). Acest lucru este util, de exemplu, pentru a verifica dacă un șir de caractere este sau nu valabil ca adresă de e-mail.

În cazul în care întregul șir se potrivește, se returnează un obiect match.

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'>

În cazul în care există părți necorespunzătoare (doar corespondențe parțiale sau nicio corespondență), se returnează None.

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

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

Funcția fullmatch() a fost adăugată în Python 3.4. Dacă doriți să faceți același lucru în versiunile anterioare, utilizați match() și un metacaracter de potrivire $ la sfârșit. Dacă întregul șir de la început până la sfârșit nu se potrivește, se returnează None.

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

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

Obțineți o listă cu toate părțile care se potrivesc: findall()

findall() returnează o listă cu toate subșirurile care corespund. Rețineți că elementele listei nu sunt obiecte de potrivire, ci șiruri de caractere.

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']

Numărul de părți care corespund poate fi verificat cu ajutorul funcției încorporate len(), care returnează numărul de elemente din listă.

print(len(result))
# 3

Gruparea cu paranteze() într-un model de expresie regulată returnează o listă de tupluri ale căror elemente sunt șirurile de caractere din fiecare grup. Acest lucru este echivalent cu groups() din obiectul match.

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

Parantezele de grup () pot fi imbricate, astfel încât, dacă doriți să obțineți și întreaga potrivire, trebuie doar să includeți întreaga potrivire între paranteze ().

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')]

Dacă nu se găsește nicio potrivire, se returnează un tuplu gol.

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

Obțineți toate părțile care se potrivesc ca un iterator: finditer()

finditer() returnează toate părțile care se potrivesc sub forma unui iterator. Elementele nu sunt șiruri de caractere, ca findall(), ci obiecte de potrivire, astfel încât puteți obține poziția (indexul) părților potrivite.

Iteratorul în sine nu poate fi tipărit cu print() pentru a obține conținutul său. Dacă utilizați funcția încorporată next() sau instrucțiunea for, puteți obține conținutul unul câte unul.

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'>

De asemenea, poate fi convertit într-o listă cu 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)

Dacă doriți să obțineți poziția tuturor părților care se potrivesc, notația de înțelegere a listei este mai convenabilă decât list().

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

Iteratorul extrage elementele în ordine. Rețineți că, dacă încercați să extrageți mai multe elemente după ce ați ajuns la sfârșit, nu veți rămâne cu nimic.

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))
# []

Înlocuiți părțile corespunzătoare: sub(), subn()

Folosind sub(), puteți înlocui partea care se potrivește cu un alt șir de caractere. Șirul substituit va fi returnat.

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'>

Atunci când se grupează cu paranteze(), șirul care se potrivește poate fi utilizat în șirul înlocuit.

În mod implicit, sunt acceptate următoarele: Rețineți că, pentru șirurile normale care nu sunt șiruri brute, trebuie să fie listată o backslash înainte de backslash pentru a scăpa backslash-ul.

\1Prima paranteză
\2A doua paranteză
\3A treia paranteză
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>
Dacă denumiți grupul scriind acest nume la începutul parantezelor modelului de expresie regulată, îl puteți specifica folosind numele în loc de număr, așa cum se arată mai jos.
\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

Argumentul count specifică numărul maxim de înlocuiri. Numai numărul din partea stângă va fi înlocuit.

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() returnează un tupluplu format din șirul de caractere substituit (la fel ca valoarea de returnare a sub()) și numărul de părți substituite (numărul de părți care corespund modelului).

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

Metoda de specificare a argumentelor este aceeași ca și în cazul sub(). Puteți utiliza partea grupată prin paranteze sau puteți specifica numărul de argumente.

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)

Divizarea șirurilor de caractere cu modele de expresii regulate: split()

split() împarte șirul în partea care corespunde modelului și îl returnează sub formă de listă.

Rețineți că prima și ultima potrivire vor conține șiruri de caractere goale la începutul și la sfârșitul listei rezultate.

s = '111aaa222bbb333'

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

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

Argumentul maxsplit specifică numărul maxim de diviziuni (bucăți). Numai numărul din partea stângă va fi împărțit.

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

Metacaracterele expresiilor regulate, secvențe speciale și avertismente în Python

Principalele metacaractere ale expresiilor regulate (caractere speciale) și secvențe speciale care pot fi utilizate în modulul Python 3 re sunt următoarele

metacaracterconținut
.Orice caracter unic, altul decât o linie nouă (inclusiv o linie nouă cu steagul DOTALL).
^Începutul șirului (se potrivește, de asemenea, cu începutul fiecărei linii cu indicatorul MULTILINE)
$Sfârșitul șirului de caractere (se potrivește, de asemenea, cu sfârșitul fiecărei linii cu indicatorul MULTILINE)
*Repetați modelul anterior de mai mult de 0 ori
+Repetați modelul anterior cel puțin o dată.
?Repetați modelul anterior de 0 sau 1 ori
{m}Repetați modelul anterior de m ori
{m, n}Ultimul model.m~nrepetă
[]Un set de caractere[]Se potrivește cu oricare dintre aceste caractere
|ORA|BSe potrivește fie cu modelul A, fie cu modelul B
secvență specialăconținut
\dNumere zecimale Unicode (limitate la numere ASCII prin indicatorul ASCII)
\D\dAdică opusul acestui lucru.
\sCaracterele de spațiere Unicode (limitate la caracterele de spațiere ASCII prin indicatorul ASCII)
\S\sAdică opusul acestui lucru.
\wCaractere de cuvânt Unicode și caractere de subliniere (limitate la caractere alfanumerice ASCII și caractere de subliniere prin indicatorul ASCII)
\W\wAdică opusul acestui lucru.

Nu toate acestea sunt enumerate în acest tabel. Consultați documentația oficială pentru o listă completă.

De asemenea, rețineți că unele dintre semnificații sunt diferite în Python 2.

Setarea steagului

După cum se arată în tabelul de mai sus, unele metacaractere și secvențe speciale își schimbă modul în funcție de indicator.

Aici sunt acoperite doar principalele steaguri. Pentru restul, consultați documentația oficială.

Limitat la caractere ASCII: re.ASCII

\wDe asemenea, se va potrivi în mod implicit cu caracterele kanji cu două octeți, caracterele alfanumerice etc. pentru șirurile Python 3. Nu este echivalentă cu următoarele, deoarece nu este o expresie regulată 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

Dacă specificați re.ASCII pentru steagurile de argument în fiecare funcție sau adăugați următorul steag inline la începutul șirului de tipare de expresie regulată, aceasta se va potrivi numai cu caracterele ASCII (nu se va potrivi cu caractere japoneze cu doi octeți, caractere alfanumerice etc.).
(?a)
În acest caz, următoarele două sunt echivalente.
\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

Același lucru se aplică și la compilarea cu re.compile(). Utilizați argumentul flags sau 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 este de asemenea disponibil ca formă scurtă re. A. Puteți utiliza fie.

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

\W, opusul lui \W, este, de asemenea, afectat de re.ASCII și de steagurile 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'>

Ca și în cazul lui \w, următoarele două se potrivesc în mod implicit atât cu caracterele de un singur octet, cât și cu cele de doi octeți, dar sunt limitate la caractere de un singur octet dacă se specifică re.ASCII sau steagurile inline.

  • Potrivește numerele\d
  • Se potrivește cu un spațiu gol\s
  • Potrivește numere care nu sunt numere\D
  • Se potrivește cu orice spațiu.\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

Nu ține cont de majuscule și minuscule:re.IGNORECASE

În mod prestabilit, este sensibil la majuscule și minuscule. Pentru a le potrivi pe ambele, trebuie să includeți atât majusculele, cât și minusculele în model.

re.IGNORECASEDacă se specifică acest lucru, se va potrivi fără a ține cont de majuscule și minuscule. Echivalent cu indicatorul i din expresiile regulate 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'>

Puteți folosi „mai mic decât” sau „egal cu”.

  • steag inline(?i)
  • abreviereare.I

Potriviți începutul și sfârșitul fiecărui rând:re.MULTILINE

^Caracterele meta din această expresie regulată se potrivesc cu începutul șirului.

În mod implicit, se potrivește doar începutul întregului șir, dar următoarele se vor potrivi și cu începutul fiecărei linii. Echivalent cu indicatorul m din expresiile regulate 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']

$Se potrivește cu sfârșitul șirului. În mod implicit, se potrivește doar sfârșitul întregului șir.
re.MULTILINEDacă specificați acest lucru, se va potrivi și la sfârșitul fiecărei linii.

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

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

Puteți folosi „mai mic decât” sau „egal cu”.

  • steag inline(?m)
  • abreviereare.M

Specificați mai multe steaguri

|Dacă doriți să activați mai multe steaguri în același timp, utilizați acest lucru. În cazul stegulețelor inline, fiecare caracter trebuie să fie urmat de o literă, așa cum se arată mai jos.
(?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']

Meciuri cu și fără lăcomie

Aceasta este o problemă generală cu expresiile regulate, nu doar o problemă cu Python, dar voi scrie despre ea pentru că are tendința de a mă băga în probleme.

În mod implicit, următoarea este o potrivire lacomă, care se potrivește cu cel mai lung șir de caractere posibil.

  • *
  • +
  • ?
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

? după el va avea ca rezultat o potrivire minimală, care se potrivește cu cel mai scurt șir de caractere posibil.

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

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

Rețineți că potrivirea lacomă implicită se poate potrivi cu șiruri de caractere neașteptate.