Regulárne výrazy v Perli - 6. časť CGI

Ako som už minule sľúbil, dnešná časť nášho rozprávania o CGI sa bude venovať Perlu, najpoužívanejšiemu jazyku pre tvorbu CGI aplikácií.


Nie však Perlu celkovo, ale povieme si niečo o regulárnych výrazoch, ktoré dávajú Perlu obrovskú silu pri spracovávaní textových dát.

Regulárne výrazy (preklad z anglického regular expressions, niekedy sa používa aj skratka regexp) sú zrejme známe všetkým užívateľom Linuxu. Perlovské reg. výrazy sú veľmi podobné tým, ktoré používa aj program egrep. Aj keď sa vám môžu zdať regulárne výrazy ako neprehľadná spleť znakov, keď ich pochopíte a pochopíte aj spôsob ich interpretovania jazykom Perl, získate pravdepodobne najsilnejší nástroj na prácu s textom, s akým ste kedy mohli pracovať.

Regulárne výrazy vlastne vykonávajú porovnávanie reťazca so zadaným vzorom. Ak je vzor v reťazci nájdený, máte niekoľko možností, ako výsledok takéhoto porovnávania využiť. Pri bežnom porovnávaní vás zaujíma, či reťazec obsahuje vzor. Ak áno, regexp vám vráti pravdivú hodnotu a vy môžete vykonať určitý blok príkazov. Ak použijete pri porovnávaní príkaz nahradenia, pri nájdení vzoru sa zamení postupnosť vyhľadávaných znakov za iný vami určený reťazec. Poslednou možnosťou porovnávania je príkaz split, s ktorým ste sa mohli stretnúť v predchádzajúcej časti nášho seriálu o CGI. Tento vráti po porovnaní všetky miesta, s ktorými sa vzor nezhoduje.

V zásade platí, že väčšina znakov v regulárnych výrazov sa zhoduje sama so sebou. Pokým v reg. výraze uvediete viac znakov za sebou, tieto sa musia zhodovať presne v danom poradí. To znamená, že ak uvediete napr. reg. výraz
/ahoj/
bude sa zhodovať len vtedy, ak daný reťazec bude obsahovať podreťazec "ahoj". Ostatné znaky sú metaznaky a samy so sebou sa nezhodujú. Ak chcete v porvnávaní použiť aj zhodu na nejaký znak, ktorý je metaznakom, musíte pred ním uviesť znak "\" (obrátené lomítko). Tu je zoznam metaznakov:
\ | ( ) [ { ^ $ * + ? .

Ako som už spomenul, obrátené lomítko mení metaznak na obyčajný znak (znakový literál). Pokým teda chcete použiť obrátené lomítko ako znakový literál, musíte použiť postupnosť znakov \\. Ak však použijete obrátené lomítko pred znakovým literálom, bude tento zmenený na metaznak alebo nejaký druh postupnosti.

Ďalšou vecou, s ktorou sa môžete pri reg. výrazoch stretnúť, sú kvantifikátory. Tieto určujú, koľkokrát po sebe sa musí zadaný vzor zhodovať. Kvantifikátory sa však viažu vždy len na znak, za ktorým nasledujú, ak chcete kvantifikovať vzor obsahujúci viac znakov, musíte tieto zoskupiť pomocou zátvoriek:
/(ahoj){2}/
čo vyvolá zhodu v prípade, ak porovnávaný reťazec bude obsahovať podreťazec "ahojahoj". Naproti tomu:
/ahoj{2}/
sa bude zhodovať s "ahojj". V nasledujúcej tabuľke sú uvedené používané kvantifikátory:

{m,n} zhoduje sa minimálne m-krát, ale maximálne n-krát
{m,} musí sa zhodovať aspoň m-krát
{m} musí sa zhodovať presne m-krát
* zhoduje sa 0 alebo viackrát (ako {0,})
+ zhoduje sa 1 alebo viackrát (ako {1,})
? zhoduje sa 0 alebo 1 krát (ako {0,1})

Určite vás teraz napadne, dobre, ale čo ak chcem porovnať reťazec na výskyt jednej z viacerých možností? Aj na toto majú regulárne výrazy prostriedok: vaše vzory jednoducho oddelíte znakom | (pipe, zvislá čiara) a váš regexp bude vyzerať nasledovne:
/Jano|Fero|Jožo|Mišo/
V takomto prípade teda bude porovnávanie úspešné, ak bude reťazec obsahovať aspoň jeden z podreťazcov Jano, Fero, Jožo alebo Mišo. Už ste pri kvantifikátoroch videli, že ak chcem nejaké vzory zoskupiť, použijem na to zátvorky. Keby som teda chcel nájsť v nejakom reťazci napr. dvojslovnú zhodu, pri čom prvé z týchto slov by mohlo byť z určitej množiny slov, použil by som nasl. výraz:
/(Jano|Fero|Jožo|Mišo) Hruška/
Takýto výraz spôsobí zhodu, ak bude nájdený podreťazec "Jano Hruška", "Fero Hruška", "Jožo Hruška" alebo "Mišo Hruška".

Keďže sú vzory porovnávané ako reťazce v úvodzovkách, funguje aj v regulárnych výrazoch vkladanie premenných. Ak teda
$foo = "ahoj";
zhodu spôsobí
/$foo/ aj /ahoj/
Vkladanie premenných však spôsobuje spomalenie porovnávania, pretože premenná sa môže meniť (veď od toho je premenná) a vzor musí byť zakaždým znovu preložený. Avšak pozor, kedykoľvek je znak "$" nasledovaný znakom pipe (zvislá čiara), uzatváracou guľatou zátvorkou alebo koncom reťazca, bude interpretovaný ako koniec riadku, nie ako vkladanie premennej.

Keďže je problematika regulárnych výrazov pomerne obsiahla, nabudúce budeme pokračovať a povieme si čosi o pravidlách porovnávania regulárnych výrazov.

Developer,
Stiahnuté z Developer.sk