Regulární výrazy v Pythonu
Jako základ (pokud není uvedeno jinak) je ve všech následujících příkladech brán tento idiom:
>>> python=u"""Python je skvělý objektově orientovaný, interpretovaný a interaktivní programovací jazyk. Často je srovnáván (samozřejmě příznivě, zeptejte se Googla ;-)) s jazyky C, Visual Basic, Java, Perl, Scheme,.... a je s ním daleko větší zábava."""
;-)
Neregulární výrazy
Člověk dlouho vystačí při hledání či nahrazování řetězců v textu s obyčejnými funkcemi, jako např.:
>>> print python.find(u"skvělý") 10 >>> print python.replace(u"skvělý",u"výborný") Python je výborný objektově orientovaný, interpretovaný a interaktivní programov ací jazyk. Často je srovnáván (samozřejmě příznivě, zeptejte se Googla ;-)) s ja zyky C, Visual Basic, Java, Perl, Scheme,.... a je s ním daleko větší zábava. >>> print python.count(u"a") 19
Jednoho dne však potřebuje, najít a vypsat např. všechna slova, která začínají na velká písmena, všechny emailové adresy nebo nahradit všechny odkazy za html formou tagu <a>. A v té chvíli buď začne vytvářet šíleně složité algoritmy za použití výše uvedených funkcí nebo se naučí používat regulární výrazy.
Jednoduché příklady,
které se sice dají dělat dělat i pomocí výše uvedených metod, ale zde slouží k seznámení s modulem re.:
>>> import re >>> re.search(u"skvělý", python) <_sre.SRE_Match object at 0x00A37138> >>> dir(re.search(u"skvělý", python)) ['__copy__', '__deepcopy__', 'end', 'expand', 'group', 'groupdict', 'groups', 's pan', 'start'] >>> re.search(u"skvělý", python).start() 10 >>> print re.sub(u"skvělý",u"výborný", python) Python je výborný objektově orientovaný, interpretovaný a interaktivní programov ací jazyk. Často je srovnáván (samozřejmě příznivě, zeptejte se Googla ;-)) s ja zyky C, Visual Basic, Java, Perl, Scheme,.... a je s ním daleko větší zábava. >>> re.findall(u"a", python) [u'a', u'a', u'a', u'a', u'a', u'a', u'a', u'a', u'a', u'a', u'a', u'a', u'a', u 'a', u'a', u'a', u'a', u'a', u'a'] >>> len(re.findall(u"a", python)) 19
Zatím regulární výrazy jsou složitější než neregulární. Jejich krása však teprve přichází.
Základní sémantika
Základ re výrazů je jiný, než je zvyklá většina z Windows/Linuxu. Ve Windows se tato konvence používá výhradně na hledání souborů, v re však na prohledávání jakéhokoliv textu.
Chceme-li obyčejně vyhledat všechny soubory, píšeme *. V re to je však .*. Tečka znamená jakýkoliv jeden znak, * pak, že se může libovolněkrát opakovat. ? obyčejně znamená přesně jeden znak, v re to je . (tečka). Těchto tzv. metaznaků je mnohem více a umí mnohem více, než jakýkoliv začátečník může jen doufat nebo si vůbec představit.
Regulární příklady se dají použít na následující typy úloh. Poznámka pro váhavé: neváhejte sem přidávat další příklady, třeba vždy, když se vám podaří něco nového s regulárními vzory vyřešit:
Najdi všechna slova, která začínají na "o"
>>> re.findall("\Wo\w*", python, re.U) [u' objektov\\u011b', u' orientovan\\xfd']
- "\Wo\w*":
- \W značí v hatmatilce regulárních výrazů jakýkoliv jeden znak, který je jiný než písmeno. Tedy mezera, tečka, uvozovky, Enter, apod. Před naším slovem nemusí být totiž jen mezera.
- "o" - zde je znak "sám za sebe". Tedy po nějakém znaku musí být "o".
- Dál může pokračovat jakékoliv písmeno (\w - jakékoliv písmeno kromě mezery - tedy opak \W), které se může libovolněkrát (0x, 1x, 2x, ....) opakovat (*) - pokaždé to může být písmeno jiné.
- python:
- prohledávaný řetězec
- re.U:
- aby nám to fungovalo i pěkně na češtinu, na Unicode
- [u' objektov\u011b', u' orientovan\xfd']:
- připadá-li vám, že to není česky, tak se mýlíte. Jen Python neumí v seznamu česky nativně tisknout, což se dá obejít tím, že seznam budete procházet v cyklu a tisknout jednotlivé položky zvlášť.
Najdi všechna slova, která začínají na malé nebo i velké S
>>> re.findall(" [sS]\w*", python, re.U) [u' skv\u011bl\xfd', u' srovn\xe1v\xe1n', u' se', u' s', u' Scheme', u' s']
Téměř to samé jako minule, jen:
- [sS]:
- Na začátku může být buď ([]) s nebo S. Buď jedno nebo druhé.
Najdi text, obsah a priponu
# -*- coding: cp1250 -*- import re text="""---bladsasda text: ahoj obsah: jirka.novy pripona: txt blasdadsbla --- ---blaasdasdla bla text: nazdar obsah: marek.zeleny pripona: txt blaasdasdbla --- ---blasdasd bla bla text: cau obsah: tonda.vokoun pripona: txt bla asdasda ---""" # "text:" - hledá slovo "text:" # "*" - předchozí znak se může libovolněkrát opakovat # " *" - mezera se může libovolněkrát oprakovat # \w - jedno písmeno, jakékoliv # \w+ - písmeno se může libovolněkrát opakovat, nejméně však jednou - jinými slovy je to "slovo" # (\w+) - bude zahrnuto do výsledku hledání jako např. skupina 1 = vyskyt.group(1) # "obsah: *" - dále musí následovat slovo "obsah" následovaný libovolným počtem mezer # (\w+\.\w+) - dvě slova oddělená tečkou, ve výsledcích to bude skupina 2 # atd. atd. vzor="text: *(\w+) *obsah: *(\w+\.\w+) *pripona: *(\w+)" # finditer postupně nalézá všechny výskyty v textu - v tomto případě po řádcích for vyskyt in re.finditer(vzor, text): # vytiskne skupinu 1 (to co je ve vzoru v první závorce, skuponu i tři) print vyskyt.group(1)+" - "+ vyskyt.group(2)+" - "+ vyskyt.group(3)
Najdi všechny emailové adresy
waiting for you ;-)
Více aneb Záložky, Oblíbené
Grafické znázornění