Regulární výraz je malý jazyk pro popis textových vzorů. Dokáže najít čísla faktur v dokumentu, rozpoznat tvar data, vytáhnout pole z logu nebo nahradit opakované mezery. Na první pohled působí krypticky, protože několik znaků interpunkce nese mnoho významů. Srozumitelným se stane ve chvíli, kdy jej přestaneme vnímat jako záhadný řetězec a začneme jej číst zleva doprava jako sérii přesných rozhodnutí o tom, jaký text může následovat.

Literály jsou nejjednodušší části vzoru

Většina písmen a číslic odpovídá sama sobě. Vzor kava hledá tyto čtyři znaky v daném pořadí. Zvláštní význam mají metaznaky jako tečka, hvězdička, závorky nebo hranaté závorky. Když mají označovat skutečnou interpunkci, je obvykle nutné je escapovat. Desetinnou tečku hledá \., protože neescapovaná tečka v mnoha enginech znamená téměř libovolný znak.

Při čtení si lze představit, že každý token žádá engine o spotřebování určité části vstupu. Literál spotřebuje sám sebe, třída jeden povolený znak a skupina spojí několik kroků do jednoho celku. Tento pohled rychle ukáže, kde vzor dovoluje více, než autor zamýšlel.

Třída znaků popisuje jednu pozici

Hranaté závorky definují množinu znaků, které mohou obsadit jedno místo. [abc] odpovídá jednomu písmenu a, b nebo c, nikoli celému slovu. Rozsah [0-9] popisuje číslici a negovaná třída vše mimo uvedenou množinu. Zkratky jako \d nebo \s jsou pohodlné, ale jejich chování vůči Unicode se může lišit podle enginu a přepínačů.

Celá slova se vybírají pomocí alternativ ve skupině, například (kocka|pes). Rozdíl mezi jedním znakem a celou sekvencí je základní, protože třída vložená pod kvantifikátor může přijmout téměř libovolné pořadí svých členů.

Kvantifikátory určují opakování

Hvězdička dovoluje nula nebo více opakování předchozího tokenu, plus vyžaduje alespoň jedno a otazník činí část volitelnou. Složené závorky vyjadřují přesný počet nebo interval. Kvantifikátor se vztahuje pouze k bezprostředně předchozímu tokenu či skupině, proto závorky zásadně mění význam.

Většina kvantifikátorů je chamtivá: nejprve spotřebuje co nejvíce textu a při neúspěchu vrací znaky, aby mohla pokračovat další část vzoru. Líná varianta naopak začíná nejkratším možným úsekem. Ani jedna není obecně správnější. Rozhodující je hranice, kterou má vzor skutečně vyjádřit.

Kotvy a hranice popisují pozici

Některé tokeny žádný znak nespotřebují. Kotvy začátku a konce vyžadují určitou pozici ve vstupu; multiline režim může jejich význam změnit na začátek a konec jednotlivých řádků. Hranice slova označuje přechod mezi slovním a neslovním znakem podle pravidel konkrétního enginu.

Samotný vzor pro číslice může najít platně vypadající úsek uvnitř delšího chybného řetězce. Kotvy z něj udělají tvrzení o celé hodnotě. Proto vyhledávací regex nelze automaticky použít pro validaci bez kontroly jeho hranic.

Skupiny organizují, zachycují a vybírají

Kulaté závorky spojují tokeny, aby se na ně vztahoval společný kvantifikátor nebo alternativa. Zachycující skupina navíc uloží nalezený text pro další zpracování či náhradu. Pojmenované skupiny jsou stabilnější než číselné pozice, protože spotřebitel pracuje s významem jako year nebo account.

Nezachycující skupina je vhodná, když je potřeba pouze struktura. Omezení zbytečných capture skupin zpřehlední záměr a zabrání tomu, aby vložení nové závorky změnilo číslování používané vzdáleným kódem.

Přepínače mění prostředí výrazu

Flags mohou zapnout ignorování velikosti písmen, multiline kotvy, shodu tečky s novým řádkem, globální hledání nebo Unicode režim. Vzor nelze správně interpretovat bez znalosti přepínačů. Stejný zdrojový text může po jejich změně vracet jiné výsledky a jiné hranice.

Liší se také samotné enginy. JavaScript, PCRE, Python, Java a .NET sdílejí základ, ale nepodporují stejné lookbehind konstrukce, pojmenování skupin ani Unicode vlastnosti. Regex z online testeru je nutné ověřit v přesném runtime a metodě, kde poběží.

Lookaround kontroluje okolí bez jeho spotřeby

Lookahead a lookbehind umí vyžadovat kontext před nebo za shodou, aniž by se tento text stal součástí výsledku. Jsou užitečné pro poziční podmínky, ale mohou snížit čitelnost a přenositelnost. Když lze stejný požadavek jasně vyjádřit zachycením a obyčejným kódem, bývá takové řešení snadněji udržovatelné.

Složitá síť negativních lookaroundů často signalizuje, že regex začal nahrazovat business pravidla. Strukturální tvar může ověřit vzor, zatímco vztahy mezi poli, rozsahy a externí znalost patří do explicitní aplikační logiky.

Nahrazování je druhý malý jazyk

Replacement string obvykle interpretuje odkazy na skupiny, dolarové znaky a zpětná lomítka. Správný vyhledávací vzor tak může stále poškodit výstup, pokud aplikace nerozumí syntaxi náhrady. Pojmenované skupiny a test celého výsledného textu snižují riziko.

Uživatelská data je vhodné vkládat pomocí API pro literální hodnotu nebo callbacku. Předání libovolného vstupu jako replacement syntaxe může nečekaně rozbalit odkazy na skupiny.

Regex je nejlepší pro omezenou lokální strukturu

Regulární výrazy vynikají tam, kde text má jasný a omezený tvar. Nejsou ideálním parserem hluboce vnořeného jazyka, libovolného HTML ani pravidel závislých na externím stavu. Mohou ověřit rozumný tvar e-mailové adresy, ale nedokážou potvrdit existenci schránky.

Stejně důležitá je volba operace. Hledání první shody, nalezení všech shod a validace celé hodnoty používají podobný vzor, ale mají jiné smlouvy. Kód má proto pojmenovat záměr a ošetřit situaci bez výsledku i více výsledků.

Dobrý vzor má omezenou odpovědnost, příklady a testy úspěšných i odmítnutých hodnot. Když jej lze přečíst token po tokenu a každou část vysvětlit běžnou větou, regex přestává být interpunkční hádankou a stává se přesným nástrojem pro práci s textem.