Kako koristiti Python modul regularnog izraza re (podudaranje, pretraživanje, pod, itd.)

Poslovanje

Za obradu regularnog izraza u Pythonu koristimo modul re iz standardne biblioteke. Omogućuje vam da izvučete, zamijenite i podijelite nizove pomoću obrazaca regularnog izraza.

U ovom ćemo odjeljku prvo objasniti funkcije i metode re modula.

  • Sastavljanje obrazaca regularnog izraza:compile()
  • odgovarajući objekt
  • Provjerite odgovara li početak niza, izdvojite:match()
  • Provjerite podudaranja koja nisu ograničena na početak:search()
  • Provjerite odgovara li cijeli niz:fullmatch()
  • Dobijte popis svih odgovarajućih dijelova:findall()
  • Dobijte sve podudarne dijelove kao iterator:finditer()
  • Zamijenite odgovarajući dio:sub(),subn()
  • Dijeljenje nizova s ​​obrascima regularnog izraza:split()

Nakon toga ću objasniti meta znakove (posebne znakove) i posebne sekvence regularnih izraza koji se mogu koristiti u re modulu. U osnovi, to je standardna sintaksa regularnog izraza, ali budite oprezni pri postavljanju zastavica (osobito re.ASCII).

  • Metaznakovi regularnog izraza, posebne sekvence i upozorenja u Pythonu
  • Postavljanje zastave
    • Ograničeno na ASCII znakove:re.ASCII
    • Ne razlikuje velika i mala slova:re.IGNORECASE
    • Spoji početak i kraj svakog retka:re.MULTILINE
    • Navedite više zastava
  • Pohlepne i nepohlepne utakmice

Sastavite obrazac regularnog izraza: compile()

Postoje dva načina za izvođenje obrade regularnog izraza u re modulu.

Pokreni s funkcijom

Prva je funkcija.re.match(),re.sub()Funkcije poput ovih dostupne su za izvođenje ekstrakcije, zamjene i drugih procesa koristeći obrasce regularnog izraza.

Pojedinosti o funkcijama bit će opisane kasnije, ali u svima njima prvi argument je niz uzorka regularnog izraza, zatim niz koji treba obraditi i tako dalje. Na primjer, u re.sub(), koji izvodi zamjenu, drugi argument je zamjenski niz, a treći argument je niz koji treba obraditi.

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

Imajte na umu da [a-z] u obrascu regularnog izraza u ovom primjeru znači bilo koji znak od a do z (tj. mala abeceda), a + znači ponavljanje prethodnog uzorka (u ovom slučaju [a-z]) jednom ili više puta. [a-z]+ odgovara bilo kojem nizu koji ponavlja jedan ili više malih abecednih znakova.

. je meta znak (znak s posebnim značenjem) i mora se izaći s obrnutom kosom crtom.

Budući da nizovi obrasca regularnog izraza često koriste puno obrnutih kosih crta, prikladno je koristiti neobrađene nizove kao u primjeru.

Izvodi se u metodi objekta uzorka regularnog izraza

Drugi način obrade regularnih izraza u re modulu je metoda objekta uzorka regularnog izraza.

Koristeći re.compile(), možete sastaviti niz uzoraka regularnog izraza kako biste stvorili objekt uzorka regularnog 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()Na primjer, isti proces kao i ove funkcije može se izvršiti kao metode match(),sub() objekata regularnog izraza.

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

Sve dolje opisane funkcije re.xxx() također su dostupne kao metode objekta regularnog izraza.

Ako ponavljate proces koji koristi isti uzorak, učinkovitije je generirati objekt regularnog izraza pomoću re.compile() i koristiti ga unaokolo.

U sljedećem primjeru koda, funkcija se koristi bez kompajliranja radi praktičnosti, ali ako želite više puta koristiti isti uzorak, preporuča se da ga prevedete unaprijed i izvršite kao metodu objekta regularnog izraza.

odgovarajući objekt

match(), search() itd. vraćaju objekt podudaranja.

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

Usklađeni niz i pozicija dobivaju se pomoću sljedećih metoda objekta podudaranja.

  • Saznajte mjesto utakmice:start(),end(),span()
  • Nabavite odgovarajući niz:group()
  • Dobijte niz za svaku grupu:groups()
print(m.start())
# 0

print(m.end())
# 11

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

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

Ako dio obrasca regularnog izraza priložite u niz sa zagradama(), dio će se obraditi kao grupa. U ovom slučaju, niz dijela koji odgovara svakoj grupi u groups() može se dobiti kao tor.

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

Provjerite odgovara li početak niza, izdvojite: match()

match() vraća objekt podudaranja ako početak niza odgovara uzorku.

Kao što je gore spomenuto, objekt podudaranja može se koristiti za izdvajanje podudarnog podniza ili jednostavno za provjeru je li napravljeno podudaranje.

match() će provjeriti samo početak. Ako na početku nema odgovarajućeg niza, vraća 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

Provjerite podudaranja koja nisu ograničena na početak, izdvojite: search()

Kao i match(), vraća objekt podudaranja ako se podudara.

Ako postoji više podudarnih dijelova, bit će vraćen samo prvi podudarni dio.

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

Ako želite dobiti sve podudarne dijelove, koristite findall() ili finditer() kako je opisano u nastavku.

Provjerite odgovara li cijeli niz: fullmatch()

Da biste provjerili odgovara li cijeli niz obrazac regularnog izraza, koristite fullmatch(). Ovo je korisno, na primjer, za provjeru je li niz valjan kao adresa e-pošte ili ne.

Ako se cijeli niz podudara, vraća se podudarni objekt.

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

Ako postoje neusklađeni dijelovi (samo djelomična podudaranja ili uopće nema podudaranja), vraća se None.

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

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

Fullmatch() je dodan u Python 3.4. Ako želite učiniti isto u ranijim verzijama, upotrijebite match() i odgovarajući meta znak $ na kraju. Ako se cijeli niz od početka do kraja ne podudara, vraća None.

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

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

Dobijte popis svih odgovarajućih dijelova: findall()

findall() vraća popis svih odgovarajućih podnizova. Imajte na umu da elementi popisa nisu podudarni objekti već nizovi.

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

Broj podudarnih dijelova može se provjeriti pomoću ugrađene funkcije len(), koja vraća broj elemenata na popisu.

print(len(result))
# 3

Grupiranje sa zagradama() u obrascu regularnog izraza vraća popis torki čiji su elementi nizovi svake grupe. Ovo je ekvivalent groupe() u objektu podudaranja.

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

Grupne zagrade () mogu biti ugniježđene, pa ako želite dobiti i cijelo podudaranje, samo stavite cijelo podudaranje u zagrade ().

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

Ako nije pronađeno podudaranje, vraća se prazan tuple.

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

Dobijte sve podudarne dijelove kao iterator: finditer()

finditer() vraća sve podudarne dijelove kao iterator. Elementi nisu nizovi kao findall(), već objekti koji se podudaraju, tako da možete dobiti poziciju (indeks) podudarnih dijelova.

Sam iterator se ne može ispisati pomoću print() da bi se dobio njegov sadržaj. Ako koristite ugrađenu funkciju next() ili for naredbu, sadržaj možete dobiti jedan po jedan.

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

Također se može pretvoriti u popis s 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)

Ako želite dobiti položaj svih podudarnih dijelova, notacija razumijevanja popisa je prikladnija od liste().

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

Iterator vadi elemente redom. Imajte na umu da ako pokušate izdvojiti više elemenata nakon što dođete do kraja, ostat ćete bez ičega.

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

Zamijenite podudarne dijelove: sub(), subn()

Koristeći sub(), podudarni dio možete zamijeniti drugim nizom. Zamijenjeni niz će biti vraćen.

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

Prilikom grupiranja sa zagradama(), podudarni niz se može koristiti u zamijenjenom nizu.

Prema zadanim postavkama podržano je sljedeće: Imajte na umu da za normalne nizove koji nisu neobrađeni nizovi, obrnuta kosa crta mora biti navedena prije obrnute kose crte kako bi se izbjegla obrnuta kosa crta.

\1Prva zagrada
\2Druga zagrada
\3Treća zagrada
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>
Ako grupi date naziv tako što ćete ovo napisati na početku zagrada obrasca regularnog izraza, možete je odrediti koristeći naziv umjesto broja, kao što je prikazano u nastavku.
\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

Broj argumenata navodi maksimalni broj zamjena. Zamijenit će se samo broj s lijeve strane.

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() vraća tuple zamijenjenog niza (isto kao povratna vrijednost sub()) i broj zamijenjenih dijelova (broj koji odgovara uzorku).

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

Metoda specificiranja argumenata ista je kao sub(). Možete koristiti dio grupiran zagradama ili navesti broj argumenata.

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)

Dijeljenje nizova s ​​obrascima regularnog izraza: split()

split() dijeli string na dijelu koji odgovara uzorku i vraća ga kao popis.

Imajte na umu da će prvo i posljednje podudaranje sadržavati prazne nizove na početku i na kraju rezultirajućeg popisa.

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 specificira maksimalni broj podjela (komada). Samo broj s lijeve strane bit će podijeljen.

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

Metaznakovi regularnog izraza, posebne sekvence i upozorenja u Pythonu

Glavni meta znakovi regularnog izraza (posebni znakovi) i posebni nizovi koji se mogu koristiti u modulu Python 3 re su sljedeći

metakaraktersadržaj
.Bilo koji pojedinačni znak osim novog retka (uključujući novi redak s oznakom DOTALL)
^Početak niza (također odgovara početku svakog retka sa zastavicom MULTILINE)
$Kraj niza (također odgovara kraju svakog retka sa zastavicom MULTILINE)
*Ponovite prethodni uzorak više od 0 puta
+Ponovite prethodni uzorak barem jednom.
?Ponovite prethodni uzorak 0 ili 1 put
{m}Ponovite prethodni uzorak m puta
{m, n}Posljednji uzorak.m~nponoviti
[]Skup znakova[]Odgovara bilo kojem od ovih znakova
|ILIA|BOdgovara ili A ili B uzorku
poseban slijedsadržaj
\dUnicode decimalni brojevi (ograničeni na ASCII brojeve pomoću ASCII zastavice)
\D\dŠto znači suprotno od ovoga.
\sUnicode znakovi razmaka (ograničeno na ASCII znakove razmaka pomoću ASCII zastavice)
\S\sŠto znači suprotno od ovoga.
\wUnicode znakovi riječi i podvlake (ograničeno na ASCII alfanumeričke znakove i podvlake ASCII zastavicom)
\W\wŠto znači suprotno od ovoga.

Nisu svi navedeni u ovoj tablici. Za potpuni popis pogledajte službenu dokumentaciju.

Također imajte na umu da su neka značenja različita u Pythonu 2.

Postavljanje zastave

Kao što je prikazano u gornjoj tablici, neki meta znakovi i posebne sekvence mijenjaju svoj način ovisno o zastavi.

Ovdje su pokrivene samo glavne zastave. Za ostalo pogledajte službenu dokumentaciju.

Ograničeno na ASCII znakove: re.ASCII

\wOvo će također odgovarati dvobajtnim kanjijem, alfanumeričkim znakovima itd. prema zadanim postavkama za Python 3 nizove. Nije ekvivalent sljedećem jer nije 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

Ako navedete re.ASCII za zastavice argumenata u svakoj funkciji ili dodate sljedeću umetnutu oznaku na početak niza uzorka regularnog izraza, odgovarat će samo ASCII znakovima (neće odgovarati dvobajtnim japanskim, alfanumeričkim znakovima itd. .).
(?a)
U ovom slučaju, sljedeća dva su ekvivalentna.
\w#ERROR![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

Isto vrijedi i za kompajliranje s re.compile(). Koristite zastavice argumenata ili inline zastavice.

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 također dostupan kao kratki oblik re. O. Možete koristiti bilo koje.

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

Na \W, suprotno od \W, također utječu re.ASCII i inline zastavice.

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

Kao i kod \w, sljedeća dva odgovaraju jednobajtnim i dvobajtnim znakovima prema zadanim postavkama, ali su ograničeni na jednobajtne znakove ako su specificirane re.ASCII ili inline zastavice.

  • Spojite brojeve\d
  • Odgovara praznom prostoru\s
  • Odgovara ne-brojevima\D
  • Odgovara bilo kojem ne-prostoru.\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

Ne razlikuje velika i mala slova:re.IGNORECASE

Prema zadanim postavkama, razlikuje se velika i mala slova. Da biste oboje uskladili, morate uključiti i velika i mala slova u uzorak.

re.IGNORECASEAko je to navedeno, podudarat će se bez obzira na velika i mala slova. Ekvivalentno zastavici i u standardnim regularnim izrazima.

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

Možete koristiti manje od ili jednako.

  • inline zastava(?i)
  • skraćenicare.I

Spoji početak i kraj svakog retka:re.MULTILINE

^Meta znakovi u ovom regularnom izrazu odgovaraju početku niza.

Prema zadanim postavkama, podudara se samo početak cijelog niza, ali će i sljedeće odgovarati početku svakog retka. Ekvivalentno zastavici m u standardnim regularnim izrazima.
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']

$Odgovara kraju niza. Prema zadanim postavkama, samo se kraj cijelog niza podudara.
re.MULTILINEAko to navedete, također će odgovarati kraju svakog retka.

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

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

Možete koristiti manje od ili jednako.

  • inline zastava(?m)
  • skraćenicare.M

Navedite više zastava

|Ako želite omogućiti više zastavica u isto vrijeme, upotrijebite ovo. U slučaju inline zastavica, svaki znak mora biti praćen slovom kao što je prikazano u nastavku.
(?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 i nepohlepne utakmice

Ovo je opći problem s regularnim izrazima, ne samo problem s Pythonom, ali pisat ću o tome jer me često dovodi u nevolje.

Prema zadanim postavkama, sljedeće je pohlepno podudaranje, koje odgovara najdužem mogućem 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

? nakon što će rezultirati ne-pohlepnim, minimalnim podudaranjem, koji odgovara najkraćem mogućem 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

Imajte na umu da zadano pohlepno podudaranje može odgovarati neočekivanim nizovima.

Copied title and URL