☰ menu
Pavel Satrapa

Regulární výrazy

Je načase opět se trochu odlišit od průměru. Vyhledávaný objekt totiž nemusí být jen pouhý řetězec znaků. Ve skutečnosti se jedná o tak zvaný regulární výraz. Jeho prostřednictvím lze zadávat i značně komplikované požadavky, které má vyhledávaný (a případně nahrazovaný, jak uvidíte v části o nahrazování textu) text splňovat.

Regulární výraz jest chápati jako jakousi šablonu, kterou vim přikládá na text a zkoumá, zda vyhovuje. V okamžiku, kdy text odpovídá šabloně, zajásá a přemístí na něj kurzor.

Základní prvky

Nejjednodušším typem regulárního výrazu je prostý znak – písmeno, číslice a podobně. Jemu vyhoví stejný znak v textu. Takže například /a hledá písmeno „a“, případně (pokud máte zapnuto :set ignorecase) i „A“. Pokud za sebou zřetězíte několik regulárních výrazů, hledá vim v textu zřetězení prvků, které vyhovují jednotlivým výrazům v tom pořadí, v němž jsou uvedeny. Důsledkem je klasické hledání řetězce. /ahoj obsahuje regulární výraz, který vznikl zřetězením čtyř elementárních, obsahujících jednotlivá písmena. Výsledkem je přirozené chování – hledá se řetězec „ahoj“.

Zobecňující výrazy

Někdy vám na jistém znaku nezáleží. To v regulárním výrazu vyznačíte tečkou (.). Například výrazu /n.c vyhoví „nic“, „noc“ i jakýkoli jiný řetězec tří znaků, který začíná písmenem „n“ a končí „c“.

Občas chcete, aby určitý znak měl jistou volnost, ale pouze v rámci vámi daných možností. V takovém případě uzavřete do hranatých závorek ([...]) seznam přípustných znaků. Hodláte-li například mezi výše zmíněnými písmeny „n“ a „c“ strpět pouze samohlásku, nechte vyhledat /n[aeiouy]c. Uvnitř hranatých závorek jsou vyjmenovány přípustné varianty pro jeden znak. Celkově tedy tomuto regulárnímu výrazu vyhoví pouze tříznakový řetězec.

Pokud by vyjmenovávaných variant bylo příliš, můžete si vypomoci pomlčkou. Dva znaky oddělené uvnitř hranatých závorek navzájem pomlčkou znázorňují interval. Vyhoví mu libovolný znak, jehož ASCII kód leží mezi uvedenými dvěma. Například číslice lze vyjádřit pomocí [0-9]. Hledáte-li tedy v textu jména souborů „xxx0“ až „xxx9“, poslouží vám regulární výraz /xxx[0-9].

Když je prvním znakem uvnitř hranatých závorek stříška (^), neguje jejich obsah. To znamená, že vyhoví libovolný znak s výjimkou těch, které jsou uvedeny v hranatých závorkách. Pokud chcete vyjádřit, že na jistém místě nesmí být písmeno, můžete použít [^a-zA-Z]. Jestliže máte vypnuto rozlišování velkých písmen od malých, stačí [^a-z].

Hranice

Další dva regulární výrazy vyznačují začátek (znak ^) a konec (znak $) řádku. Hledáte-li řádek, začínající slovem „From“, použijte /^From. Specialitou je hledání prázdného řádku, které obstará /^$ (za začátkem má ihned následovat konec).

Příbuznými znaků pro začátek a konec řádku jsou symboly \< a \>. První označuje začátek slova a druhé jeho konec. Kdybyste například hledali zvratnou částici „se“, nebylo by příliš šťastné použít /se. V tomto případě by totiž vim hledal řetězec „se“ i uvnitř slov, jako je sekera, konsekvence či recese. Při použití /\<se\> jsou podobné nadbytečné výskyty vyloučeny.

Opakování

Velmi důležitým prvkem regulárních výrazů je opakování. Pokud se předchozí regulární výraz může opakovat, přidejte za něj hvězdičku (*). Ovšem pozor! Hvězdička může znamenat i nulový počet opakování. Hledáte-li řádky, složené ze samých pomlček, můžete použít /^-*$. Takovému výrazu však vyhoví i řádky prázdné. Pokud chcete, aby vim vyhledal jen řádky s alespoň jednou pomlčkou, nasaďte /^--*$. Zde je požadováno, aby za začátkem řádku následovala pomlčka a po ní pak libovolný počet dalších.

Jelikož požadavek na alespoň jeden výskyt je poměrně častý, zavedl vim pro jeho ztělesnění další speciální znak. Je jím plus (\+). Výraz a\+ má tedy stejný význam jako aa*.

Opakování je „hladové“ – snaží se do sebe vždy pohltit co největší počet znaků a teprve pak pokračuje v analýze zbytku regulárního výrazu. Například ve výrazu .*-.* první .* zahrne všechny znaky až k poslední pomlčce, - bude odpovídat poslední pomlčka a druhému .* všechny znaky za ní.

Proto text v uvozovkách nelze vybrat pomocí ".*". Vyhovělo by mu vše od prvních uvozovek na řádku až po poslední. Místo všech znaků je třeba uvnitř opakovat znaky kromě uvozovek, tedy "[^"]*".

Dalším často používaným počtem je nepovinný výskyt. Tedy test na nanejvýš jeden výskyt daného řetězce. Ve vim se vyznačuje pomocí \= nebo \?. Pokud byste například hledali koncovky HTML souborů, které mohou být .htm či .html, poslouží vám /\.html\=\>. Dvojznak \= za posledním písmenem říká, že „l“ v řetězci může být a nemusí. Kombinace \? je v regulárních výrazech tradiční pro vyjádření nepovinnosti, ovšem ve vim ji nelze použít pro hledání směrem zpět (pomocí ?), proto doporučuji dávat přednost \=.

Speciální znaky

Možná jste si povšimli konstrukce \. v příkladu z předchozího odstavce. Jejím prostřednictvím je zadán požadavek na výskyt tečky. vim používá obvyklé konvence operačního systému Unix. Pokud mají některé znaky speciální význam (jako například „.“, „*“, „$“ či „\“), lze je do regulárního výrazu vložit tak, že jim předsadíte zpětné lomítko. Proto hledáte-li hvězdičku, zdejte \* a při odhalování zpětných lomítek vám pomůže \\.

Závorky a zapamatování

Opakování se týká pouze posledního regulárního výrazu. V řetězci ahoj\+ se proto opakování vztahuje jen na písmeno „j“, nikoli na celé slovo „ahoj“. Pokud chcete do opakování zahrnout víceznakový regulární výraz, obalte jej speciálními závorkami ve tvaru \( a \). V našem případě by regulární výraz vypadal takto: \(ahoj\)\+.

Závorky mají ve skutečnosti ještě mnohem zajímavější funkci. vim si totiž zapamatuje řetězec, který jim vyhověl, a později jej můžete použít. Speciální konstrukce \n totiž představuje n-tý zapamatovaný řetězec. Tato schopnost se uplatní především při nahrazování, ale i v hledání ji občas můžete výhodně využít. Pokud například hledáte pětiznakové palindromy (slova, která se nemění, když jsou čtena pozpátku, například „rotor“), nasaďte \(.\)\(.\).\2\1. Editor vyhledá všechny řetězce, obsahující libovolný znak (který si zapamatuje pod číslem 1), za ním ještě jeden libovolný znak (zapamatován pod číslem 2) a ještě jeden, za nímž následuje znak zapamatovaný pod číslem 2 a na závěr ještě první zapamatovaný.

Nebo

Posledním vylepšením regulárních výrazů je možnost vyjádřit „nebo“. Zajistí ji dvojznak \|. Hledáte-li slovo „ahoj“ nebo „nazdar“, můžete použít příkaz /ahoj\|nazdar. Nebo má ze všech zde zmiňovaných konstrukcí nejnižší prioritu. Dvojznaky \| vlastně rozdělí regulární výraz na několik částí. vim pak vyhledá řetězce, které vyhovují alespoň jedné z nich.

Víceřádkové vzory

Jednou z tradičních vlastností regulárních výrazů je jejich omezení na jeden řádek. Od verze 6 však tohle ve vim už neplatí. Nyní lze do regulárního výrazu zařadit dvojznak \n, kterému vyhoví jedině konec řádku. Můžete jej používat i uvnitř hranatých závorek, takže například [ \n] znamená „tady může být mezera nebo konec řádku“.

Druhým způsobem, jak vzít do hry konec řádku, je předřazení kombinace \_ před některé speciální znaky. Například tečka reprezentuje libovolný znak kromě konce řádku. Trojici znaků \_. však vyhoví libovolný znak včetně konce řádku.

Podobně znaky ^ a $ se mohly vyskytnout jen na začátku/konci regulárního výrazu, aby měly svůj speciální ohraničující význam. Hledáte-li ^ab, hledá se řetězec „ab“ na začátku řádku. Hledáte-li a^b, hledá se řetězec „a^b“ kdekoli. Nyní máte k dispozici konstrukce \_^ a \_$, které představují začátek/konec řádku kdekoli v regulárním výrazu. Takže například regulární výraz ^[0-9].*\n\_^- hledá řádek, který začíná číslicí a řádek za ním začíná pomlčkou. Všimněte si konstrukce .*\n, která říká „tady mohou být libovolné znaky a za nimi konec řádku“. Reprezentuje zbytek prvního řádku (text za úvodní číslicí).