# Regulárne výrazy

     Tento dodatok obsahuje krátky ale snád dostatočný úvod do sveta
    regulárnych výrazov. Popisuje regulárne
    výrazy tak, ako sa používajú v &kate;, ktoré nie sú kompatibilné
    s výrazmi z jazyka perl ani s tými napr. z príkazu grep.

## Úvod

Regulárne výrazy poskytujú spôsob, ako popísať obsah textu spôsobom, ktorý chápe malý softvérový systém, takže je možné zistiť, či text odpovedá zadanému výrazu a v prípade pokročilejších aplikácií aj spôsob, ako uložiť časti odpovedajúceho textu.

Príklad: Povedzme, že chcete nájsť text pre odstavce, ktorý začína bud menami Henrik alebo Pernille nasledovaný nejakým tvarom slovesa say.

Pri normálnom hľadaní by sme začali hľadať prvé meno Henrik, možno nasledované písmenami sa: `Henrik sa` a počas hľadania by sme zahadzovali tie nájdené texty, ktoré by nezačínali odstavec a tie, kde sa nie je začiatkom says, said a podobne. A potom by sme to zopakovali s druhým menom...

S regulárnymi výrazmi sa dá táto úloha dokončiť jediným hľadaním a to dokonca presnejšie.

Aby sme to dosiahli, regulárne výrazy definujú pravidlá pre vyjadrenie detailov a generalizácie hľadania textu. Náš príklad, ktorý sa dá popísať ako Riadok začítajúci bud Henrik alebo Pernille (prípadne na začiatku môžu byť až 4 medzery alebo tabulátory) nasledovaný prázdnymi znakmi po ktorých je sa a potom bud ys alebo id je možné vyjadriť týmto regulárnym výrazom:

`^[ \t]{0,4}(Henrik|Pernille) sa(ys|id)`

Uvedený príklad demonštruje všetky štyri hlavné koncepty moderných regulárnych výrazov, a to:

- Vzorky

- Podmienky

- Kvantifikátory

- Spätné referencie

Znak `^` na začiatku výrazu je podmienka, ktorá platí iba v prípade, nasledujúci odpovedajúci reťazec je na začiatku riadku.

Reťazce `[ \t]` a `(Henrik|Pernille) sa(ys|id)` sú vzorky. Prvá je trieda znakov, ktorá odpovedá bud medzere alebo (horizontálnemu) tabulátoru. Dalšia vzorka obsahuje prvý podreťazec odpovedajúci bud `Henrik` alebo `Pernille`, potom je kus odpovedajúci presne `sa` a nakoniec podvzorka odpovedajúca bud `ys` alebo `id`

Reťazec `{0,4}` je kvantifikátor hovoriaci niečo medzi 0 až 4 výskytmi predchádzajceho.

Pretože regulárne výrazy podporujú koncept spätných referencií, čo znamená uloženie celého odpovedajúceho textu alebo aj jeho časti uzavreté v zátvorkách a prístup k nim, môžete pracovať bud s celým nájdeným textom (pri hľadaní v textovom dokumente v editore pomocou regulárneho výrazu je to často označený text) alebo s nájdeným menom alebo koncovkou slovesa.

Všetko dohromady, tento výraz nájde presne to, čo chceme, a iba to.

Nasledujúce kapitoly detailne popisujú ako vytvárať a používať vzorky, triedy znakov, podmienky, kvalifikátory a spätné referncie. Na konci je uvedených niekoľko užitočných príkladov.

## Vzorky

Vzorky obsahujú reťazce a triedy znakov. Vzorky môžu obsahovať pod-vzorky, čo sú vzorky v zátvorkách.

### Escaped znaky

Vo vzorkách a triedach znakov majú niektoré znaky špeciálny význam. Aby ste ich mohli hľadať, musia byť označené ako escaped aby softvér pochopil, že ich má hľadať a nie použiť ich špeciálny význam.

To sa zariadi pridaním pred ne spätné lomítko (`\`).

Softvér bude potichu ignorovať escaped znaky, ktoré nemajú žiadny špeciálny význam, takže to, že ho použijete napríklad pre j (`\j`) je vporiadku. Ak neviete, či má znak špeciálny význam, môžete mu kľudne pridať `\`.

### Triedy znakov a skratky

Trieda znakov je výraz, ktorý odpovedá jednému z definovanej množiny znakov. Triedy znakov sa definujú pridaním znakov do hranatých zátvoriek `[]` alebo pomocou niektorej zo skratiek definovaných nižšie.

Jednoduché triedy znakov obsahujú iba jeden alebo viac znakov, napríklad `[abc]` (odpovedá písmenu a, b alebo c) alebo `[0123456789]` (odpovedá číslici).

Pretože písmená a číslice majú logický poriadok, môžete ich skrátiť pomocou intervalov: `[a-c]` je to isté ako `[abc]` a `[0-9]` je to isté ako `[0123456789]`. Ich kombinácia, napríklad `[a-fynot1-38]` je tiež prípustná (tento príklad odpovedá samozrejme jeden znak z a,b,c,d, e,f,y,n,o,t, 1,2,3 alebo 8).

Veľké písmená sú iné ako malé písmená. Aby ste vytvorili triedu, ktorá nerozlišuje veľké a malé písmená pre a a b, musíte použiť `[aAbB]`.

Je samozrejme možné uviesť aj negatívnu triedu, ktorá odpovedá všetkému okrem toho, čo je v triede uvedené. Na to sa používa `^` na začiatku triedy:

`[^abc]` nájde všetky znaky okrem a, b or c.

Okrem normálnych znakov sú definované niektoré skrátky, aby bol život trochu jednoduchší:

`\a`

  Toto odpovedá ASCII znaku zvonček (BEL, 0x07).

`\f`

  Toto odpovedá znaku ASCII form feed (FF, 0x0C).

`\n`

  Toto odpovedá znaku ASCII line feed (LF, 0x0A, nový riadok v systémoch Unix).

`\r`

  Toto odpovedá znaku ASCII carriage return (CR, 0x0D).

`\t`

  Toto odpovedá znaku horizontálneho tabulátora ASCII (HT, 0x09).

`\v`

  Toto odpovedá znaku ASCII vertikálnho tabulátora (VT, 0x0B).

`\xhhhh`

  Toto odpovedá znaku Unicode s hexadecimálnym číslom hhhh (between 0x0000 and 0xFFFF). \0ooo (čiže \zero ooo) odpovedá ASCII/Latin-1 znaku s osmičkovým kódom ooo (medzi 0 a 0377).

`.` (bodka)

  Toto odpovedá ľubovoľnému znaku (aj konci riadku).

`\d`

  Toto odpovedá číslici. Rovnaké ako `[0-9]`

`\D`

  Toto odpovedá nie číslici. Rovnaké ako `[^0-9]` alebo `[^\d]`

`\s`

  Toto odpovedá znakom prázdneho miesta. Prakticky rovnaké ako `[ \t\n\r]`

`\S`

  Toto odpovedá nie prázdnemu miestu. Prakticky rovnaké ako `[^ \t\r\n]`, a presne rovnaké ako `[^\s]`

`\w`

  Odpovedá znakom slov - v tomto prípade písmená alebo číslice. Všimnite si, že podtržítko (`_`) neodpovedá, čo je rozdiel oproti regulárnym výrazom jazyka perl. Rovnaké ako `[a-zA-Z0-9]`

`\W`

  Odpovedá znakom, ktoré netvoria slová - všetko okrem písmen a číslic. Rovnaké ako `[^a-zA-Z0-9]` alebo `[^\w]`

Skratky pre triedy je možné dávať do vlastných tried, napríklad pre nájdenie písmen slov, medzery alebo bodky je možné použiť `[\w \.]`

Notácia tried štandardu POSIX , `[:<meno triedy>:]` momentálne nie je podporovaná.

#### Znaky so špeciálnym významom v triedach znakov

Nasledujúce znaky majú špeciálny význam v konštukcii [] a preto musia byť escaped:

`]`

  Ukončuje triedu znakov. Musí byť escaped ak to nie je prvý znak triedy alebo je priamo za `^`.

`^`

  Označuje negatívnu triedu, ak je uvedený ako jej prvý znak. Ak sa má priamo hľadať, musí byť escaped v prípade, že je na prvom mieste v triede.

`-` (pomlčka)

  Označuje rozsah znakov. Musí byť v triede vždy escaped.

`\` (spätné lomítko)

  Znak pre escaped znaky. Musí byť vždy escaped.

### Alternatívy: hľadanie jeden z

Ak chcete nájsť jednu z alternatív vzoriek, môžete alternatívy oddeliť pomocou `|`.

Napríklad pre nájdenie John alebo Harry, mali by ste použiť výraz `John|Harry`.

### Pod-vzorky

Pod-vzorky sú vzorky v zátvorkách a majú vo svete regulárnych výrazov niekoľko použití.

#### Špecifikácia alternatív

Pod-vzorky môžete použiť pre zoskupenie alternatív do väčšej vzorky. Alternatívy sú oddelené znakom |.

Napríklad, aby sa našli slová int, float alebo double, môžete použiť vzorku `int|float|double`. Ak chcete nájsť iba jedno z nich nasledované práznym miestom a potom nejakými písmenami, zadajte alternatívy do pod-vzorky: `(int|float|double)\s+\w+`.

#### Zachytenie odpovedajúceho textu (spätné referencie)

Ak chcete používať spätné referencie, použite pod-vzorky pre uloženie častí, o ktoré máte záujem.

Napríklad, ak chcete nájsť dva výstkyty rovnakého slova oddelené čiarkou a nejakým prázdnym miestom, môžete použiť`(\w+),\s*\1`. Pod-vzorka `\w+` nájde skupinu písmen slova a celý výraz odpovedá tým, za ktorými je čiarka 0 alebo viac prázdnych znakov a potom skupina znakov slov. (Reťatec `\1` označuje prvú pod-vzorku v zátvorkách)

Prečítajte si aj Spätné referencie.

#### Podmienky pre výhľad

Podmienky pre výhľad je pod-vzorka začínajúca `?=` alebo `?!`.

Napríklad, ak chcete nájsť reťazec Bill ale iba v prípade, že za ním nie je Gates, môžete použiť tento výraz: `Bill(?! Gates)`. (Toto nájde text Bill Clinton aj Billy the kid, ale ignoruje iné texty.)

Pod-vzorky používané pre podmienky sa nezachytávajú.

Prečítajte si aj Podmienky

### Znaky so špeciálnym významom vo vzorkách

Nasledujúce znaky majú vo vzorkách špeciálny význam, preto musia byť escaped v prípade, že ich chcete hľadať:

`\` (spätné lomítko)

  Znak pre escaped.

`^`

  Podmienka pre začiatok reťazca.

`$`

  Podmienka pre koniec reťazca.

`()` (ľavá a pravá zátvorka)

  Označuje pod-vzorky.

`{}` (ľavá a pravá zložená zátvorka)

  Označuje číslené kvantifikátory.

`[]` (ľavá a pravá hranatá zátvorka)

  Označuje triedy znakov.

`|`

  logické OR. Oddeľuje alternatívy.

`+` (plus)

  Kvantifikátor, 1 alebo viac.

`*` (hviezdička)

  Kvantifikátor, 0 alebo viac.

`?` (otáznik)

  Nepovinný znak. Dá sa interpretovať ako kvantifikátor 0 alebo 1.

## Kvantifikátory

Kvantifikátory umožňujú, aby regulárne výrazy odpovedali zadanému počtu alebo rozsahu opakovaní znaku, triedy znakov alebo pod-vzoriek.

Kvantifikátory sú zatvorené v zložených zátvorkách (`{` a `}`) a majú tvar `{[minimum-opakovaní][,[maximum-opakovaní]]}`

Použitie je asi najjasnejšie z príkladov:

`{1}`

  Presne jeden výskyt

`{0,1}`

  Jeden alebo žiadny výskyt

`{,1}`

  To isté ale menej písania :-)

`{5,10}`

  Aspoň 5 ale maximálne 10 výskytov.

`{5,}`

  Aspoň 5 výskytov, žiadne obmedzenie zhora.

Navyše sú definované niektoré skratky:

`*` (hviezdička)

  podobné `{0,}`, nájde ľubovoľné množstvo opakovaní.

`+` (plus)

  podobné `{1,}`, aspoň 1 výskyt.

`?` (otáznik)

  podobné `{0,1}`, 0 alebo 1 výskyt.

### Greed

Pri použití kvantifikátorov bez maxima sa regulárne výrazy snažia nájsť čo najdlhší reťazec, čo sa obvykle označuje ako chovanie greedy.

Moderné regulárne výrazy poskytujú možnosť vypnutia tohto chovania, ale v grafickom rozhraní vám to musí umožniť aplikácia sama. Napríklad v dialógu pre hľadanie môžete mať voľbu označenú Minimálne hľadanie tak, aby bolo jasné, ako sa hľadá a aké je štandardné chovanie.

### Príklady v kontexte

Tu je pár príkladov použitia kvantifikátorov

`^\d{4,5}\s`

  Odpovedá čísliciam v 1234 go a 12345 now, ale nie v 567 eleven ani v 223459 somewhere

`\s+`

  Odpovedá jednému alebo viacerým prázdnym znakom

`(bla){1,}`

  Odpovedá všetkým blablabla ale nie bla v blackbird alebo tabla

`/?>`

  Odpovedá /> v <closeditem/> aj > v <openitem>.

## Podmienky

Podmienky umožňujú, aby regulárny výraz odpovedal textu iba pri niektorých podmienkach.

Podmienka nepotrebuje žiadne znaky na to, aby platila. Funguje skôr ako kontrola svojho okolia na nejaký odpovedajúci text bez jeho akceptovania. Napríklad okraj slova sa nepokúša uistiť, že na jednej strane je znak slova a na druhej nie je, ale skôr testuje, či tam nie je znak slova. To znamená, že táto podmienka bude platiť aj ked tam žiadny znak nie je, napríklad na konci prehľadávaného textu.

Niektoré podmienky nepotrebujú vzorku, ale časť reťazca, ktorý nebude súčasťou nájdeného textu.

Regulárne výrazy podporujú tieto podmienky:

`^` (začiatok reťazca)

  Odpovedá začiatku prehľadávaného reťazca.

  Výraz `^Peter` bude platiť na Peter v reťazci Peter, hey! ale nie v Hey, Peter!

`$` (koniec reťazca)

  Odpovedá konci prehľadávaného reťazca.

  Výraz `you\?$` bude odpovedať na posledom you v reťazci You didn't do that, did you? ale nie v You didn't do that, right?

`\b` (okraj slova)

  Odpovedá, ak je na jednej strane znak slova a na druhej nie slovo.

  Toto sa hodí pre hľadanie konca slov, napríklad pre oba konce slova. Výraz `\bin\b` bude odpovedať samostatnému in v reťazci He came in through the window, ale nie in v window.

`\B` (nie okraj slova)

  Odpovedá vždy, ked nepodpovedá \b.

  To znamená, že bude odpovedať napríklad vnútri slov. Výraz `\Bin\B` bude odpovedať v window ale nie v integer alebo I'm in love.

`(?=VZORKA)` (Pozitívny výhľad)

  Podmienka s výhľadom sa pozrie na časť reťazca, ktorá je až za textom, ktorý odpovedá. Pozitívny výhľad zabráni tomu, aby reťazec odpovedal v prípade, že neodpovedá VZORKE podmienky, ale text odpovedajúci tejto vzorke nebude vo výsledu zahrnutý.

  Výraz `handy(?=\w)` odpovedá handy v handyman ale nie v That came in handy!

`(?!VZORKA)` (Negatívny výhľad)

  Negatívny výhľad zabráni možnému nájdeniu v prípade, že nasledujúci reťazec odpovedá VZORKE.

  Výraz `const \w+\b(?!\s*&)` odpovedá const char v reťazci const char* foo ale nebude odpovedať const QString v const QString& bar, pretože & odpovedá vzorke podmienky negatívneho výhľadu.

## Spätné referencie