Za obdelavo regularnih izrazov v Pythonu uporabimo modul re iz standardne knjižnice. Omogoča pridobivanje, nadomeščanje in deljenje nizov z uporabo vzorcev regularnih izrazov.
- re — Regular expression operations — Python 3.10.0 Documentation
- Regular Expression HOWTO — Python 3.10.0 Documentation
V tem razdelku bomo najprej razložili funkcije in metode modula re.
- Sestavljanje vzorcev regularnih izrazov:
compile()
- predmet ujemanja
- Preveri, ali se začetek niza ujema, izvleček:
match()
- Preverite, ali se ujemajo z začetkom:
search()
- Preveri, ali se ujema celoten niz:
fullmatch()
- Pridobite seznam vseh ustreznih delov:
findall()
- Pridobi vse ujemajoče se dele kot iterator:
finditer()
- Zamenjajte ustrezen del:
sub()
,subn()
- Deljenje nizov z vzorci regularnih izrazov:
split()
Nato bom razložil meta znake (posebne znake) in posebna zaporedja regularnih izrazov, ki jih je mogoče uporabiti v modulu re. V osnovi gre za standardno sintakso regularnih izrazov, vendar bodite previdni pri nastavljanju zastavic (zlasti re.ASCII).
- Metaznaki regularnih izrazov, posebna zaporedja in opozorila v programu Python
- Nastavitev zastave
- Omejeno na znake ASCII:
re.ASCII
- Ni občutljivo na velikost črk:
re.IGNORECASE
- Ujemite začetek in konec vsake vrstice:
re.MULTILINE
- Določite več zastavic
- Omejeno na znake ASCII:
- Pohlepne in nepožrešne tekme
- Sestavi vzorec regularnega izraza: compile()
- predmet ujemanja
- preveri, ali se začetek niza ujema, izvleček: match()
- preverjanje ujemanj, ki niso omejena na začetek, izvleček: search()
- Preverite, ali se ujema celoten niz: fullmatch()
- Pridobi seznam vseh ujemajočih se delov: findall()
- Pridobi vse ustrezne dele kot iterator: finditer()
- Zamenjajte ustrezne dele: sub(), subn()
- Deljenje nizov z vzorci regularnih izrazov: split()
- Metaznaki regularnih izrazov, posebna zaporedja in opozorila v programu Python
- Nastavitev zastave
- Pohlepne in nepožrešne tekme
Sestavi vzorec regularnega izraza: compile()
Obdelavo regularnih izrazov v modulu re lahko izvedete na dva načina.
Delujte s funkcijo
Prva je funkcija.re.match()
,re.sub()
Funkcije, kot so te, so na voljo za izvajanje izločanja, nadomeščanja in drugih postopkov z uporabo vzorcev regularnih izrazov.
Podrobnosti funkcij bodo opisane pozneje, vendar je pri vseh prvi argument niz vzorca regularnega izraza, sledi niz, ki ga je treba obdelati, in tako naprej. Na primer, v funkciji re.sub(), ki izvaja zamenjavo, je drugi argument niz za zamenjavo, tretji argument pa niz, ki ga je treba obdelati.
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
Upoštevajte, da [a-z] v vzorcu regularnega izraza v tem primeru pomeni katerikoli znak od a do z (tj. mala abeceda), + pa pomeni, da prejšnji vzorec (v tem primeru [a-z]) ponovite enkrat ali večkrat. Vzorec [a-z]+ ustreza kateremu koli nizu, ki ponavlja enega ali več znakov male abecede.
. je meta znak (znak s posebnim pomenom) in ga je treba izogniti s povratno poševnico.
Ker nizi vzorcev regularnih izrazov pogosto uporabljajo veliko povratnih lomk, je priročno uporabiti neobdelane nize, kot je prikazano v tem primeru.
Deluje v metodi objekta vzorca regularnega izraza
Drugi način obdelave regularnih izrazov v modulu re je objektna metoda vzorca regularnih izrazov.
S funkcijo re.compile() lahko sestavite niz vzorcev regularnih izrazov in ustvarite objekt vzorca regularnega izraza.
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()
Enak postopek kot te funkcije se lahko na primer izvede kot metode match(),sub() objektov regularnih izrazov.
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
Vse spodaj opisane funkcije re.xxx() so na voljo tudi kot metode objekta regularnega izraza.
Če ponavljate postopek, ki uporablja isti vzorec, je učinkovitejše ustvariti objekt regularnega izraza s funkcijo re.compile() in ga uporabiti naokrog.
V naslednjem vzorcu kode je funkcija zaradi priročnosti uporabljena brez kompiliranja, če pa želite večkrat uporabiti isti vzorec, je priporočljivo, da jo predhodno kompilirate in izvedete kot metodo objekta regularnega izraza.
predmet ujemanja
match(), search() itd. vrnejo predmet 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'>
Ujemani niz in položaj se pridobita z naslednjimi metodami objekta match.
- Pridobi lokacijo tekme:
start()
,end()
,span()
- Pridobi ujemajoči se niz:
group()
- Pridobi niz za vsako skupino:
groups()
print(m.start())
# 0
print(m.end())
# 11
print(m.span())
# (0, 11)
print(m.group())
# aaa@xxx.com
Če del vzorca regularnega izraza zaprete v niz z oklepaji(), bo del obdelan kot skupina. V tem primeru lahko niz dela, ki se ujema z vsako skupino v grup(), dobite kot 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')
preveri, ali se začetek niza ujema, izvleček: match()
match() vrne predmet match, če se začetek niza ujema z vzorcem.
Kot smo že omenili, lahko objekt match uporabimo za izpis ujemajočega se podreza ali pa preprosto preverimo, ali je prišlo do ujemanja.
match() preveri samo začetek. Če na začetku ni ustreznega niza, vrne 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
preverjanje ujemanj, ki niso omejena na začetek, izvleček: search()
Podobno kot funkcija match() vrne predmet match, če se ujema.
Če je več ujemajočih se delov, bo vrnjen samo prvi ujemajoči se del.
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'>
Če želite pridobiti vse ujemajoče se dele, uporabite funkcijo findall() ali finditer(), kot je opisano spodaj.
Preverite, ali se ujema celoten niz: fullmatch()
Če želite preveriti, ali se celoten niz ujema z vzorcem regularnega izraza, uporabite funkcijo fullmatch(). To je uporabno na primer za preverjanje, ali je niz veljaven kot e-poštni naslov ali ne.
Če se ujema celoten niz, se vrne predmet ujemanja.
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'>
Če se deli ne ujemajo (samo delna ujemanja ali sploh nobeno ujemanje), se vrne vrednost None.
s = '!!!aaa@xxx.com!!!'
m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# None
Funkcija fullmatch() je bila dodana v Pythonu 3.4. Če želite enako narediti v prejšnjih različicah, uporabite match() in ustrezni meta znak $ na koncu. Če se celoten niz od začetka do konca ne ujema, vrne None.
s = '!!!aaa@xxx.com!!!'
m = re.match(r'[a-z]+@[a-z]+\.com$', s)
print(m)
# None
Pridobi seznam vseh ujemajočih se delov: findall()
funkcija findall() vrne seznam vseh ustreznih podrejencev. Upoštevajte, da elementi seznama niso objekti ujemanja, temveč nizi.
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']
Število ujemajočih se delov lahko preverite z vgrajeno funkcijo len(), ki vrne število elementov na seznamu.
print(len(result))
# 3
Združevanje v skupine z oklepaji() v vzorcu regularnega izraza vrne seznam nizov, katerih elementi so nizi vsake skupine. To je enakovredno funkciji groups() v objektu match.
result = re.findall(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(result)
# [('aaa', 'xxx', 'com'), ('bbb', 'yyy', 'com'), ('ccc', 'zzz', 'net')]
Skupinski oklepaji () so lahko vgnezdeni, zato, če želite dobiti tudi celotno ujemanje, celotno ujemanje zapišite v oklepaj ().
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')]
Če ni najdeno nobeno ujemanje, se vrne prazen tuple.
result = re.findall('[0-9]+', s)
print(result)
# []
Pridobi vse ustrezne dele kot iterator: finditer()
finditer() vrne vse ujemajoče se dele kot iterator. Elementi niso nizi kot pri funkciji findall(), temveč objekti ujemanja, zato lahko dobite položaj (indeks) ujetih delov.
Iteratorja samega ni mogoče izpisati s funkcijo print(), da bi dobili njegovo vsebino. Če uporabite vgrajeno funkcijo next() ali stavek for, lahko vsebino dobite eno za drugo.
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'>
V seznam ga lahko pretvorite tudi s funkcijo 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)
Če želite pridobiti položaj vseh ujemajočih se delov, je zapis za razumevanje seznama priročnejši od zapisa list().
print([m.span() for m in re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)])
# [(0, 11), (13, 24), (26, 37)]
Iterator vzame elemente po vrstnem redu. Upoštevajte, da če boste po koncu poskušali izločiti več elementov, vam ne bo ostalo nič.
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))
# []
Zamenjajte ustrezne dele: sub(), subn()
S funkcijo sub() lahko ujemajoči se del nadomestite z drugim nizom. Vrnjen bo zamenjani niz.
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'>
Pri združevanju z oklepaji() lahko v nadomeščenem nizu uporabimo usklajeni niz.
Privzeto so podprte naslednje možnosti: Pri običajnih nizih, ki niso surovi nizi, je treba pred povratno poševnico navesti povratno poševnico, da se ta izogne povratni poševnici.
\1 | Prvi oklepaj |
\2 | Drugi oklepaj |
\3 | Tretji oklepaj |
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>
Če skupino poimenujete tako, da to zapišete na začetku oklepajev vzorca regularnega izraza, jo lahko določite z imenom namesto s številko, kot je prikazano spodaj.\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
Argument count določa največje število zamenjav. Zamenjano bo samo število z leve strani.
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() vrne tuple nadomeščenega niza (enako kot povratna vrednost sub()) in število nadomeščenih delov (število delov, ki ustrezajo vzorcu).
result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# ('new-address, new-address, ccc@zzz.net', 2)
Način določanja argumentov je enak kot pri sub(). Uporabite lahko del, združen v oklepajih, ali določite število argumentov.
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)
Deljenje nizov z vzorci regularnih izrazov: split()
split() razdeli niz na delu, ki ustreza vzorcu, in ga vrne kot seznam.
Upoštevajte, da bosta prvo in zadnje ujemanje vsebovala prazne nize na začetku in koncu seznama.
s = '111aaa222bbb333'
result = re.split('[a-z]+', s)
print(result)
# ['111', '222', '333']
result = re.split('[0-9]+', s)
print(result)
# ['', 'aaa', 'bbb', '']
Argument maxsplit določa največje število delitev (kosov). Razdeljeno bo samo število z leve strani.
result = re.split('[a-z]+', s, 1)
print(result)
# ['111', '222bbb333']
Metaznaki regularnih izrazov, posebna zaporedja in opozorila v programu Python
Glavni meta znaki regularnih izrazov (posebni znaki) in posebna zaporedja, ki jih je mogoče uporabiti v modulu Python 3 re, so naslednji
metaznak | vsebina |
---|---|
. | katerikoli posamezni znak razen nove vrstice (vključno z novo vrstico z zastavico DOTALL). |
^ | Začetek niza (ustreza tudi začetku vsake vrstice z zastavico MULTILINE) |
$ | Konec niza (ustreza tudi koncu vsake vrstice z zastavico MULTILINE) |
* | Prejšnji vzorec ponovite več kot 0-krat. |
+ | Prejšnji vzorec ponovite vsaj enkrat. |
? | Ponovite prejšnji vzorec 0- ali 1-krat. |
{m} | Ponovite prejšnji vzorec m-krat. |
{m, n} | Zadnji vzorec.m ~n ponovite |
[] | Nabor znakov[] ustreza kateremu koli od teh znakov |
| | ALIA|B Ujema se z vzorcem A ali B |
posebno zaporedje | vsebina |
---|---|
\d | decimalna števila Unicode (omejena na števila ASCII z zastavico ASCII) |
\D | \d Pomeni nasprotno od tega. |
\s | beli znaki Unicode (omejeni na bele znake ASCII z zastavico ASCII) |
\S | \s Pomeni nasprotno od tega. |
\w | Besedni znaki Unicode in podčrtaji (omejeni na alfanumerične znake ASCII in podčrtane znake z zastavico ASCII) |
\W | \w Pomeni nasprotno od tega. |
V tej preglednici niso navedeni vsi. Celoten seznam je na voljo v uradni dokumentaciji.
Upoštevajte tudi, da so nekateri pomeni v Pythonu 2 drugačni.
Nastavitev zastave
Kot je prikazano v zgornji tabeli, nekateri meta znaki in posebna zaporedja spreminjajo svoj način glede na zastavico.
Tu so zajete le glavne zastave. Za ostale glejte uradno dokumentacijo.
Omejeno na znake ASCII: re.ASCII
\w
Privzeto se bo to ujemalo tudi z dvobajtnimi kanji, alfanumeričnimi znaki itd. za nize Python 3. Ni enakovreden naslednjemu, ker ni standardni regularni izraz.[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
Če za zastavice argumentov v vsaki funkciji določite re.ASCII ali na začetek niza vzorcev regularnih izrazov dodate naslednjo zastavico v vrstici, se bodo ujemali samo znaki ASCII (ne bodo se ujemali dvobajtni japonski znaki, alfanumerični znaki itd.).(?a)
V tem primeru sta naslednji dve enakovredni.\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
Enako velja za sestavljanje s funkcijo re.compile(). Uporabite argument flags ali 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 je na voljo tudi kot kratka oblika re. A. Uporabite lahko.
print(re.ASCII is re.A)
# True
Na \W, ki je nasprotje \W, vplivata tudi re.ASCII in inline zastave.
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'>
Tako kot pri \w se naslednja dva privzeto ujemata z enobajtnimi in dvobajtnimi znaki, vendar sta omejena na enobajtne znake, če so določene oznake re.ASCII ali inline.
- Ujemanje številk
\d
- ujema prazen prostor
\s
- ujema številke, ki niso številke
\D
- Ujema se s katerim koli znakom, ki ni presledek.
\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
Ni občutljivo na velikost črk:re.IGNORECASE
Privzeto je občutljiv na velike in male črke. Če želite, da se ujemata obe vrsti črk, morate v vzorec vključiti tako velike kot male črke.
re.IGNORECASE
Če je to določeno, se bo ujemalo brez upoštevanja velikih in malih črk. Enakovredno oznaki i v standardnih regularnih izrazih.
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'>
Uporabite lahko manj kot ali enako.
- inline zastavica
(?i)
- okrajšava
re.I
Ujemite začetek in konec vsake vrstice:re.MULTILINE
^
Meta znaki v tem regularnem izrazu se ujemajo z začetkom niza.
Privzeto se ujema le začetek celotnega niza, vendar se v naslednjem primeru ujema tudi začetek vsake vrstice. Enakovredno oznaki m v standardnih regularnih izrazih.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']
$
Ujema konec niza. Privzeto se ujema samo konec celotnega niza.re.MULTILINE
Če to določite, se bo ujemal tudi s koncem vsake vrstice.
result = re.findall('[a-z]+$', s)
print(result)
# ['zzz']
result = re.findall('[a-z]+$', s, flags=re.MULTILINE)
print(result)
# ['xxx', 'yyy', 'zzz']
Uporabite lahko manj kot ali enako.
- inline zastavica
(?m)
- okrajšava
re.M
Določite več zastavic
|
Če želite omogočiti več zastavic hkrati, uporabite to. Pri vrstičnih zastavicah mora vsakemu znaku slediti črka, kot je prikazano spodaj.(?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']
Pohlepne in nepožrešne tekme
To je splošna težava z regularnimi izrazi, ne le težava v Pythonu, vendar bom o njej pisal, ker me običajno spravi v težave.
Privzeto je naslednje ujemanje požrešno in ustreza najdaljšemu možnemu nizu.
*
+
?
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
Za znakom ? se prikaže minimalno ujemanje, ki ni pohlepno in ustreza najkrajšemu možnemu nizu.
*?
+?
??
m = re.match(r'.+?com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
print(m.group())
# aaa@xxx.com
Upoštevajte, da lahko privzeto požrešno ujemanje ustreza nepričakovanim nizom.