2.36. Grupe i sidra

Uzorak može učiniti više od pukog „ovaj niz odgovara” – može razdvojiti podudarane dijelove i predati svaki od njih aplikaciji po imenu. Zagrade oko dijela uzorka pretvaraju ga u grupu za hvatanje; objekt podudaranja zatim svaku grupu izlaže kao zaseban podniz.

2.36.1. Grupe za hvatanje

Omotajte bilo koji dio uzorka u (...) da uhvatite ono čemu odgovara:

>>> import re
>>> m = re.search(r'temp (\d+) at (\d+)s', 'temp 42 at 137s ok')
>>> m.group(0)
'temp 42 at 137s'
>>> m.group(1)
'42'
>>> m.group(2)
'137'
  • Grupa 0 uvijek je cijelo podudaranje.

  • Grupe 1, 2, … su uhvaćeni podnizovi, numerirani slijeva nadesno prema svojoj otvarajućoj zagradi.

  • Pozivanje match.group() s indeksom iza posljednje grupe baca IndexError.

Uobičajen je obrazac „podudari poznatu strukturu, uhvati promjenjive dijelove kao cijele brojeve”:

def parse_temp(line):
    m = re.search(r'temp (\d+) at (\d+)s', line)
    if not m:
        return None
    return int(m.group(1)), int(m.group(2))

2.36.2. Grupe bez hvatanja

Zagrade također grupiraju podizraz tako da se kvantifikator može primijeniti na cijelu grupu. To je jedina svrha grupiranja u r'(ab)+' – „jedan ili više ab„. Činjenica da se ab pojavljuje kao grupa 1 nuspojava je.

Za grupiranje bez hvatanja koristite (?:...)

>>> re.search(r'(?:ab)+', 'xababy').group(0)
'abab'

Grupe bez hvatanja održavaju brojeve grupa urednima kad uzorak koristi grupiranje radi strukture, ali ne mari za izdvajanje svakog dijela.

2.36.3. Sidra

Sidra ne podudaraju znak – podudaraju poziciju.

  • ^ – početak niza.

  • $ – kraj niza.

Sidra su ono što čini da se re.match() i re.search() ponašaju različito. re.match(p, s) isto je kao re.search('^' + p, s): prisiljava uzorak da počne na poziciji 0. Dodavanje $ na kraj uzorka zatim čini da uzorak podudara cijeli niz i ništa drugo:

>>> re.search(r'^\d+$', '12345')
<match num=1>
>>> re.search(r'^\d+$', '12345 ok') is None
True

^ i $ u MicroPython modulu re uvijek znače početak i kraj cijelog niza proslijeđenog u re.search(). Ne postoji re.MULTILINE zastavica koja bi ih natjerala da se podudaraju na svakom ugrađenom prijelomu retka, a $ ne podudara ni poziciju ispred završnog \n – mora biti apsolutni kraj ulaza. Za ponašanje po retku, najprije podijelite ulaz po prijelomima retka i pokrenite uzorak na svakom retku.

2.36.4. Skupovi znakova

Uglate zagrade definiraju eksplicitan skup znakova. Podudaranje troši točno jedan znak iz skupa.

  • [abc] – jedan od a, b, c.

  • [a-z] – jedan znak u rasponu a-z (uključivo).

  • [a-zA-Z0-9] – slova ili znamenke. Tri raspona kombinirana.

  • [^abc]ne jedan od a, b, c. Znak ^ negira samo kad je prvi znak unutar zagrada.

Primjeri:

>>> re.search(r'[A-F0-9]{6}', 'colour #1a2b3c rest').group(0)
'1A2B3C'
>>> re.search(r'[A-F0-9]{6}', 'colour #1a2b3c rest') is None
True

Prvi poziv u praksi vraća None jer je doslovni tekst u malim slovima. MicroPython modul re nema re.IGNORECASE zastavicu – za podudaranje neovisno o veličini slova, upišite oba oblika u skup:

>>> re.search(r'[A-Fa-f0-9]{6}', 'colour #1a2b3c rest').group(0)
'1a2b3c'

Kratice klasa (\d, \s, \w i njihovi negirani oblici) mogu se koristiti i unutar [...]: [\w-] znači „znakovi riječi ili doslovna crtica”.

2.36.5. Pohlepni naspram lijenih kvantifikatora

Kvantifikatori *, +, ? i {m,n} prema zadanom su pohlepni – podudaraju onoliko znakova koliko će ostatak uzorka i dalje dopustiti. Često je to upravo ono što se želi; ponekad nije:

>>> re.search(r'<(.+)>', 'a <b> <c> d').group(1)
'b> <c'

Pohlepni .+ zgrabio je sve do posljednjeg >. Dodavanjem ? kvantifikator postaje lijen – podudara što je manje moguće:

>>> re.search(r'<(.+?)>', 'a <b> <c> d').group(1)
'b'

Lijeni oblik staje na prvom >. Lijeni kvantifikatori stalno se pojavljuju pri izdvajanju uravnoteženih graničnika iz niza.

2.36.6. Povratne reference u zamjeni

re.sub() može se u zamjenskom nizu pozvati natrag na uhvaćene grupe putem \1, \2, … Zamjena prepisuje svako podudaranje koristeći uhvaćene dijelove:

>>> re.sub(r'(\d+)\.(\d+)', r'\2.\1', 'swap 12.34 and 5.6')
'swap 34.12 and 6.5'

Svako podudaranje hvata dva broja, a zamjena ih izmjenjuje. \g<1> je alternativna sintaksa za istu stvar – korisna kad je sljedeći znak u zamjeni znamenka (r'\g<1>0' da se grupi 1 dometne doslovna nula, umjesto čitanja „grupa 10”).

2.36.7. Što nije dostupno

Podsjetnik na ono što MicroPython modul re ne podržava, za slučaj da ovdje doluta uzorak iz CPythona i iznenadi vas:

  • Pogled unaprijed (?=...) i pogled unatrag (?<=...) – nisu implementirani.

  • Imenovane grupe (?P<name>...) i imenovane povratne reference (?P=name) – nisu implementirane.

  • Konstante zastavica poput re.IGNORECASE, re.MULTILINE, re.DOTALL – ne uvažavaju se. Izgradite skup neovisan o veličini slova ili sami unaprijed podijelite ulaz.

  • Metode match.groups(), match.span(), match.start() i match.end() ograničene su na ROM razinu koju nijedna isporučena OpenMV ploča ne omogućuje. Kod koji se oslanja na njih neće se izvoditi na kameri.

S uzorcima, grupama i sidrima, skup regex alata na kameri dovoljno je malen da se nauči u jednom sjedenju i dovoljno bogat da obavi sve osim kontekstno osjetljivog parsiranja.