Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Software
Obcování s ďáblem 17: Regulární výrazy
15. listopadu 2001, 00.00 | Dnešní díl bude tak trošku teoretický. Namísto toho, abychom si ukázali nějaké konkrétní příkazy a jejich využití, budeme se zabývat regulárními výrazy. Časem ale uvidíte, že existuje dlouhá řada případů, kde je znalost regulárních výrazů k
nezaplacení.
Co to vlastně je?
Regulární výraz je textový řetězec, který podle určitých pravidel (jimiž se budeme právě dnes zabývat) dělí všechny možné ostatní textové řetězce do dvou skupin: na ty, jež danému regulárnímu výrazu odpovídají (neboli v programátorském slangu "mačují" z anglického "match"), a na ty ostatní.
My jsme se už s něčím podobným setkali: připomeňme si třetí díl, ve které jsme se naučili určovat specifikace souborů v shellu s využitím hvězdiček a hranatých závorek. Regulární výrazy fungují velmi podobně; nabízejí však mnohem bohatší paletu možností.
A k čemu je to dobré?
Samozřejmě, základní službou, ke které se regulární výrazy používají, je vyhledávání textů: hledání všech řádků v dokumentu, na kterých se vyskytuje text, který odpovídá danému regulárnímu výrazu; hledání všech takových řetězců a záměna jinými a podobně.
Představte si, že máte rozsáhlý projekt, ve kterém se v mnoha zdrojových souborech používá volání funkce "ellipse(x,y,r1,r2)" — kde samozřejmě x, y, r1 a r2 jsou obecné výrazy, určující střed elipsy a oba její poloměry. Na nových knihovnách se třeba objeví nová služba "circle(r,x,y)", která je mnohem efektivnější; chtěli bychom proto předělat všechna volání "ellipse" ve kterých je r1 stejné jako r2 na volání "circle" — nejenže musíme ověřit, zda je r1 a r2 stejné, ale navíc musíme změnit pořadí argumentů a jeden z nich vypustit. Bez regulárních výrazů bychom to museli dělat ručně; s nimi je to poměrně snadné.
Nebo jiný příklad: vzhledem k tomu, že server MujMac není schopen akceptovat standardní HTML entity, nemohu pro psaní těchto článků použít přímo HTML editor. Píši je proto jako obyčejný ASCII text, a HTML tagy vkládám automaticky. Je-li např. za sebou řada odstavců, jež nejsou odděleny prázdnou řádkou, a každý z nich začíná znakem '-', převede se takový text na HTML seznam (<UL>...</UL>). S využitím editoru sed a regulárních výrazů je to snadné; jinak bych si na to musel psát poměrně komplikovaný převodní program...
Základní výrazy
Základní regulární výrazy vždy odpovídají jednomu znaku. Např. jeden z nejjednodušších regulárních výrazů je "a" — ten odpovídá právě znaku 'a' a žádnému jinému. Podobně jako u souborů v shellu můžeme i zde použít třeba "[abc]" pro kterýkoli ze znaků 'a', 'b' nebo 'c'.
Jakýkoli znak vyjma speciálních
Základní regulární výraz, který neobsahuje nic jiného než obyčejný znak ("a", "X", " ",...) odpovídá právě tomuto znaku, a ničemu jinému.
Seznam speciálních znaků bohužel trochu závisí na konkrétní aplikaci, jež regulární výrazy interpretuje. Vždy však mezi speciální znaky patří '.', '[', '*' a '\'; často také '$', '^', '?', '+', '{', '(' a ')'. Naopak, nikdy mezi speciální znaky nepatří písmena a čísla. Pokud jsme na pochybách, nejjednodušší je to jednou vyzkoušet (nebo se podívat do nápovědy man).
V každém případě chceme-li sestavit regulární výraz, který odpovídá některému ze speciálních znaků, použijeme před ním "escape" znak '\'. Regulární výraz, který odpovídá tečce, tedy vypadá takto: "\."; chceme-li najít hvězdičku, můžeme použít regulární výraz "\*".
Seznam alternativ
Podobně jako v shellu, můžeme i v regulárních výrazech použít seznam znaků v hranatých závorkách; takový regulární výraz odpovídá kterémukoli z vyjmenovaných znaků. Chceme-li tedy napsat regulární výraz, jemuž odpovídají právě znaky 'a', 'b', 'c' nebo 'd', můžeme použít "[abcd]".
Regulární výrazy nabízejí řadu fint pro snazší určení takovýchto seznamů. Prvním z nich je to, že můžeme použít pomlčku ve významu "od - do": namísto regulárního výrazu "[abcd]" z minulého příkladu bychom mohli napsat ekvivalentní "[a-d]". V tomto konkrétním případě je to samozřejmě téměř lhostejné; málokomu by se však asi chtělo rozepisovat bez této možnosti regulární výraz pro jakékoli písmenko nebo číslo "[a-zA-Z0-9]"!
Chceme-li "mečovat" všechny znaky kromě známého seznamu, stačí hned za první hranatou závorku zapsat znak '^': regulárnímu výrazu "[^0-9a-fA-F]" např. odpovídají právě všechny znaky, které není možné použít v zápisu hexadecimálního čísla.
Pro některé často používané množiny znaků dokonce existují speciální jména. Ta vždy začínají dvojicí "[:" a končí dvojicí ":]", aby se dala dobře rozeznat:
- "[:alpha:]" pro písmenka, "[:digit:]" pro číslice, a "[:alnum:]" pro obojí (takže regulární výrazy "[[:alnum:]]" a "[[:digit:][:alpha:]]" jsou ekvivalentni);
- "[:xdigit:]" pro znaky, odpovídající hexadecimálním číslicím;
- "[:space:]" pro oddělovače;
- řadu dalších, ne tak často využívaných možností může zájemce najít v nápovědě man grep.
Povšimněte si, že hranaté závorky ve jménech množin znaků nemají nic společného s hranatými závorkami, jež representují seznam alternativ — zatímco tedy regulární výraz "[[:alpha:]]" odpovídá libovolnému písmenu, regulární výraz "[:alpha:]" by odpovídal jen znakům ':', 'a', 'l', 'p' nebo 'h'!
Je třeba se znímit ještě o tom, že uvnitř hranatých závorek neplatí speciální znaky (např. tečka zde representuje prostě tečku, hvězdička hvězdičku atd.), že znak '^' můžeme vložit do seznamu pokud nebude první, znak ']' naopak pokud bude první, a znak '-' pokud bude poslední. Např. "[]^-]" je tedy regulární výraz, kterému odpovídá kterýkoli ze znaků ']', '^' nebo '-' — ani jeden z nich zde nemá svůj speciální význam, popsaný výše.
Žolík
Tečka má v regulárních výrazech stejný význam, jaký měl otazník ve jménech souborů v shellu: regulárnímu výrazu "." může odpovídat libovolný znak.
Zatracený Mistr Jan!
Hned na začátku je třeba upozornit, že bohužel regulární výrazy (tak, jak jsou k dispozici v řadě standardních příkazů) se nedokáží moc dobře vyrovnat se znaky s diakritickými znaménky. Regulární výraz "[a-z]" tedy rozhodně nebude odpovídat třeba znaku 'č' nebo znaku 'á'; o nic lepší to nebude ani s výrazem "[[:alpha:]]".
Ostatně ani v Terminálu nemůžeme standardně používat ne-ASCII znaky: někdy (např. v příkazu tr) bychom je mohli vkládat pomocí jejich kódů, jindy není možné ani to. Bohužel, nic se s tím nedá dělat: když byl před desítkami let Unix se svými příkazy navrhován, pracovalo se se základní šestadvacetipísmenkovou abecedou, a o ničem jiném se nikomu ani nesnilo.
Samozřejmě, že časem budou tato omezení mizet, ale počkáme si na to hezky dlouho...
Příště...
...si ukážeme několik speciálních výrazů, a vysvětlíme si že, jak a hlavně proč mohou některé regulární výrazy odpovídat i prázdnému řetězci.
Obsah seriálu (více o seriálu):
- Obcování s ďáblem
- Obcování s ďáblem 2 - základy
- Obcování s ďáblem 3 - Práce se soubory
- Obcování s ďáblem 4 - Další práce se soubory
- Obcování s ďáblem 5 - Stále soubory, hlavně linky
- Obcování s ďáblem 6: Pár zbývajících drobností
- Obcování s ďáblem 7: Samá voda, přihořívá, hoří!
- Obcování s ďáblem 8: Jak se do shellu volá, tak se program ozývá
- Obcování s ďáblem 9: Nové finty na programy
- Obcování s ďáblem 10: Do fronty, pánové, do fronty!
- Obcování s ďáblem 11: Standardní vstup a výstup
- Obcování s ďáblem 13: Další triky
- Obcování s ďáblem 14: Vyšší škola hledání souborů
- Obcování s ďáblem 15: Příkaz find stokrát jinak
- Obcování s ďáblem 16: Co se ještě dá uvařit z příkazu find
- Obcování s ďáblem 17: Regulární výrazy
- Obcování s ďáblem 18: Speciální regulární výrazy
- Obcování s ďáblem 19: Skládání regulárních výrazů
- Obcování s ďáblem 20: Regulární výrazy se zpětnými odkazy
- Obcování s ďáblem 21:K čemu je dobrý grep...
- Zázraky ihned, nemožné na počkání: sed
- Obcování s ďáblem - další finty s příkazem sed
- Rozsáhlejší příklad se sedem
- Obcování s ďáblem: Další kouzla, aneb awk
- Awk a proměnné
- Obcování s ďáblem 27: Awk a výrazy
- Obcování s ďáblem: Awk a funkce
- Awk a příkazy
- Co je to vlastně "uživatel"?
- Vlastnictví objektů
- Přístupová práva
- Vlastník, skupina, ostatní...
- Jak je to se skupinami?
- Skupiny a uživatelé
- Scripty
- Komentáře, a volba shellu
- Pro skript může být shell cokoli!
- Shellové skripty a argumenty
- Skripty a proměnné: aritmetika
- Proměnné shellu, "dědění" hodnot
- Práce s proměnnými
- Práce se jmény souborů
- Pole hodnot
- Další triky kolem polí...
- Standardní proměnné shellu
- Základní příkazy pro skripty
- Příkaz if
- Speciální podmínkové příkazy
- Podmínky pro práci se soubory
- Jednoduchý cyklus
- Příkaz for a pomocné příkazy break a continue
- Příkaz case
- Příkazy exit a select
- Rejstřík a přehled
- Procesy
- Informace o procesech
- Další klíčová slova pro příkaz ps
- Příkaz ps: několik praktických přepínačů
- A k čemu že je "ps" dobré?
- Copak procesor, s pamětí je to horší
- Virtuální paměť
- A ještě jednou virtuální paměť
- Zpět k příkazu ps
- Skutečný žrout paměti
- Ještě jednou top
- Doplněk k topu: vm_stat
- Co to tedy všechno znamená?
- Nevychází nám dal a má dáti?
- Kam se stránky ukládají?
- Změna odkládacího disku
- Změna odkládacího disku / fstab
- Poslední poznámka k fstab
- A jak to je se soubory?
- Co vlastně příkaz lsof vypisuje?
- Příkaz lsof a obsah sloupce NAME
- SIPS - Terminál není jen pro nadšence UNIXu
- Tak nám zabili NetInfo, paní Müllerová