Regulární výrazy (6.) – další zpracování

Prvních pět dílů seriálu o regulárních výrazech se zabývalo tím, jak tyto výrazy zformulovat – jejich stavebními bloky a tím, jak je skládat dohromady. Neřešili jsme ale otázku, co s regulárním výrazem, když už je napsaný. Na to odpoví až dnešní díl, ve kterém si povíme něco o vyhledávání, nahrazování a dalších operacích s regulárními výrazy, včetně několika nových zápisů, které se pro tyto účely dají vhodně využít.

Regulární výrazy mají čtyři hlavní uplatnění: Vyhledání výrazu v textu, nahrazení výrazu jiným výrazem, ověření, že text má očekávaný tvar, a „rozebrání“ textu na komponenty (pro další zpracování). První dva jsou vhodné i pro „ruční“ použití regulárních výrazů při práci s vhodným textovým editorem, druhé dva jsou typické pro strojové zpracování v rámci nějakého programu (zpracování formuláře z webové stránky, YouTube Downloader). (Popis jednotlivých použití bude v dalším textu poněkud přeházen, aby lépe vyhovoval logickým návaznostem)

Vyhledávání v textu

Skoro všechno, co jsem o regulárních výrazech napsal v předchozích dílech, se týkalo právě téhle funkce. Máme text, máme pozici v tomto textu (kurzor), a chceme najít první (druhý, třetí…) výskyt určitého výrazu v tomto textu. Implementace regulárních výrazů prochází vstupní text od pozice kurzoru směrem ke konci a hledá první místo, které zadanému regulárnímu výrazu vyhovuje; jakmile toto místo najde, označí si začátek výskytu a pokračuje co nejdál, co to jde, aby regulární výraz stále platil; na tomto místě pak vyznačí konec výskytu, celý nalezený úsek nějakým způsobem prezentuje uživateli (např. v textovém editoru tento úsek označí jako blok) a kurzor umístí za poslední znak úseku (aby se při dalším hledání pokračovalo až za nalezeným úsekem).

Dejme tomu, že čtu knihu 20000 mil pod mořem od Julese Verna, a chci postupně najít všechny výskyty slova Nautilus. Textem je v tomto případě text knihy, kurzor je před prvním hledáním na začátku a budu hledat regulární výraz \blo[dď]\p{L}**):

[Kurzor]Prchající skalisko

Rok 1866 se proslavil podivnou událostí, nevysvětleným a nevysvětlitelným jevem, na který patrně dosud nikdo nezapomněl. Pověsti, jež se rozlétly mezi lidem z přístavů a vzrušily i veřejnost daleko ve vnitrozemí, zneklidnily nejvíc námořníky. O záhadný jev se zajímali hlavně obchodníci, loďaři, lodní kapitáni, evropští i američtí rejdaři, důstojníci válečného loďstva všech zemí a po nich i vlády různých států na obou pevninách.

V poslední době se totiž několik lodí setkalo na moři s „obrovskou věcí”, s dlouhým vřetenovitým tělesem, které někdy světélkovalo a bylo mnohem větší a rychlejší než velryba.

Zprávy o tomto jevu, zanesené do různých lodních deníků, shodovaly se dost přesně v popisu tvaru onoho předmětu, jeho nevypočitatelné rychlosti, překvapivých pohybů a zdánlivě úplně zvláštní životnosti. Jestliže to byl nějaký kytovec, pak svou velikostí předčil všechny, které věda až dosud popsala. Ani Cuvier, ani Lacepede, ani Duméril, ani Quatrefages by byli nepřipustili existenci takového netvora – ledaže by ho spatřili vlastníma vědeckýma očima.

Když se vzal průměr z mnoha různých pozorování, když se vyloučily nejisté dohady, které přisuzovaly předmětu délku šedesáti metrů, když se zavrhlo přehnané tvrzení o dvoukilometrové šířce a šestikilometrové délce, bylo možno souhlasit s tvrzením, že rozměry oné úžasné bytosti přesahují vše, co ichtyologové až dosud připouštěli – jestliže ovšem ta bytost vůbec existovala!

Verne, Jules: Dvacet tisíc mil pod mořem. Praha: Státní nakladatelství dětské knihy, 1961. 423 str.

*) \b značí začátek slova, lo je prostě text „lo“, [dď] symbolizuje jedno z písmen „d“ nebo „ď“ (viz druhý díl seriálu) a \p{L}* značí „libovolný počet unicode písmen“ (viz pátý díl). Výrazu tedy vyhoví nejen loď, ale také jeho různé tvary a příbuzná slova – loděnice, lodní atd.

První hledání začne hned na začátku textu v místě označeném jako [Kurzor] a vyhledá slovo loďaři v prvním odstavci:

Rok 1866 se proslavil podivnou událostí, nevysvětleným a nevysvětlitelným jevem, na který patrně dosud nikdo nezapomněl. Pověsti, jež se rozlétly mezi lidem z přístavů a vzrušily i veřejnost daleko ve vnitrozemí, zneklidnily nejvíc námořníky. O záhadný jev se zajímali hlavně obchodníci, [Začátek bloku]loďaři[Konec bloku][Kurzor], lodní kapitáni, evropští i američtí rejdaři, důstojníci válečného loďstva všech zemí a po nich i vlády různých států na obou pevninách.

Další hledání bude pokračovat od tohoto místa a najde lodní (hned následující slovo). Atd.

Rok 1866 se proslavil podivnou událostí, nevysvětleným a nevysvětlitelným jevem, na který patrně dosud nikdo nezapomněl. Pověsti, jež se rozlétly mezi lidem z přístavů a vzrušily i veřejnost daleko ve vnitrozemí, zneklidnily nejvíc námořníky. O záhadný jev se zajímali hlavně obchodníci, loďaři, [Začátek bloku]lodní[Konec bloku][Kurzor] kapitáni, evropští i američtí rejdaři, důstojníci válečného loďstva všech zemí a po nich i vlády různých států na obou pevninách.

Z hlediska regulárních výrazů je tento způsob použití velmi přímočarý a jednoduchý a mimo jiné se obejde bez použití podskupin ve významu objektu, na který se dá odkazovat (viz třetí díl). Jedinou složitost do něj zavádí případné použití některých pokročilých podskupin, zejména look-aroundů (viz čtvrtý díl) – ostatní pokročilé podskupiny pravděpodobně nevyužijete, ale look-aroundy se hodí, protože dovolují najít text i „mimo vyznačený výsledek“: dejme tomu, že chcete vyhledat slovo Nautilus, ale s tím, že kurzor (a tedy i konec bloku) má být hned za písmenem l. Mohli byste pochopitelně hledat pouze Nautil, což by se dokonce obešlo bez potřeby regulárních výrazů, až na to, že by se vám hledání zastavovalo také na slovech jako Nautila nebo Nautilovou. Můžete ale s úspěchem využít toho, že look-aroundy sice tvoří součást hledání, ale už ne součást výsledku (tzn. musí se na daném místě vyskytovat, ale nebudou zahrnuty do označeného bloku), a hledat \bNautil(?=us\b) (začátek slova, text „Nautil“, následovaným look-aheadem „us“ + konec slova).

Ověření, že text má očekávaný tvar

Tato funkce se typicky používá v programech, zejména tam, ve kterých se očekává nespolehlivý vstup, u kterého je tudíž před zpracováním třeba ověřit, že odpovídá očekávaným parametrům. Pokud například budu od uživatele získávat rodné číslo, má smysl ověřit, že zadaný vstup splňuje aspoň formální požadavky na rodná čísla, a neukládat blbosti jako „neřeknu“ nebo „12345“.

Z hlediska regulárních výrazů jde téměř vždy jen o běžné vyhledávání s tím, že jsou použity znaky ^ (začátek textu) i $ (konec textu) – konec konců mě nezajímá, že někde uprostřed kilobajtového textu je uložené rodné číslo, já chci mít text, který obsahuje jenom rodné číslo a nic jiného. Regulární výraz bude: ^[0-9]{6}[/ ]?[0-9]{3,4}$ (začátek textu, šest číslic, volitelné lomítko nebo mezera, tři nebo čtyři číslice, konec textu).

Je však třeba si uvědomit, že regulární výrazy nejsou pro ověření správnosti samospásným nástrojem. Pokud chcete mít rozumně dlouhý a složitý regulární výraz, postihnete jenom základní formální stránku údaje (v příkladu s rodným číslem to, že bude mít správný tvar), ale ne drobnější detaily uvnitř výrazu (třetí a čtvrtý znak, obsahující měsíc, by měl být jen v rozmezí 01-12 resp. 51-62). Příslušným zesložitěním výrazu by se daly vyřešit i některé z těchto detailů (měsíc v rodném čísle), skoro vždy ale narazíte na to, že něco se regulárními výrazy zkontrolovat nedá (dělitelnost rodného čísla jedenácti, například). Což je mimochodem důvod, proč se třeba pro kontrolu e-mailové adresy běžně používají triviální zápisy typu ^.+@.+$ (zavináč a z obou stran kolem něj aspoň jeden znak) a ne úplnější ^[a-z0-9._-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$ nebo dokonce moje oblíbená „demozrůdnost“ Mail::RFC822::Address – složitost rychle narůstá a stejně nakonec zjistíte, že pro plné ověření e-mailu je potřeba na tento e-mail poslat aktivační kód a nechat uživatele, aby ho někam přepsal jako kontrolu, že ten aktivační kód dostal (a tudíž mu ta mailová adresa buď patří, nebo ji aspoň dokáže vybírat).

Rozebrání textu na komponenty

Běžně se v programech setkáváme s úkolem, vzít nějaký vstup, rozdělit ho na jednotlivé části a tyto části pak zpracovat. V YouTube Downloaderu například očekávám, že mi uživatel zadá internetovou adresu; já potřebuji v první řadě zjistit, ke kterému serveru ta adresa patří (protože z YouTube se stahuje úplně jinak než z České televize, například) a mnohdy ji před použitím upravit na jiný tvar (například u YouTube mohu dostat adresu v asi šesti základních tvarech (http://www.youtube.com/watch?v=b5AWQ5aBjgE, ale také http://www.youtube.com/embedded/b5AWQ5aBjgE nebo http://www.youtube.com/v/b5AWQ5aBjgE), z nichž se dá přímo použít jen ten první, a to ještě jen v některých případech (například by nefungoval, kdyby video bylo označené jako pro dospělé). Všechny tvary ale mají někde uvnitř uložené ID videa (v tomto případě b5AWQ5aBjgE), ze kterého lze vygenerovat adresu, která už bude společná pro všechna možná videa (a tedy vhodná pro další zpracování).

Oba popsané problémy (identifikace serveru, „vytáhnutí“ ID videa) se dají poměrně snadno a rychle řešit pomocí regulárních výrazů v jejich pojetí jako nástroje pro „rozebrání textu na komponenty“ (textem je v tomto případě adresa videa od uživatele).

Stejně jako bylo ověření tvaru vstupu jen speciálním typem vyhledávání, i rozebrání vstupu na komponenty vychází z vyhledávání. Jeho typickou charakteristikou je využití podskupin jako podvýrazů, na které se dá odkazovat – použitá knihovna pro práci s regulárními výrazy nejen najde hledaný výraz (stejně, jako to udělala u běžného vyhledávání), ale nějakým vhodným způsobem zpřístupní programátorovi i nalezené podskupiny; on si je potom vyzvedne do jednotlivých proměnných a pak už s nimi může snadno pracovat.

Jednoduchý příklad: Na vstupu máme datum v často používaném tvaru 2011-05-21 (21. května 2011). Rozebereme ho regulárním výrazem ^([0-9]{4})-([0-9]{2})-([0-9]{2})$, který nejenže to datum vyhledá a ověří (to bychom se ještě obešli bez závorek), ale také připraví pro programátora tři skupiny – v první bude rok, ve druhé měsíc a ve třetí den (připomínám ze třetího dílu, že každý uzávorkovaný kus vytvoří jednu podskupinu, očíslovanou odleva podle pořadí levé závorky, počínaje jedničkou, protože nula je vyhrazena pro celý nalezený výraz). Například v PHP by se to dalo použít takto (používám regulární výrazy podle POSIX, přestože jsou už zastaralé a nedoporučené, abych vás zbytečně nemátl dodatečnými vlastnostmi PCRE výrazů):

$text = '2011-05-21'; // vstupni text
$regexp = '^([0-9]{4})-([0-9]{2})-([0-9]{2})$'; // regularni vyraz
if (ereg($regexp, $text, $match))
{
  // Pokud se dostanu sem, byl regularni vyraz v textu nalezen
  // a do pole $match mi PHP vlozilo jednotlive podskupiny.
  $rok = $match[1]; 
  $mesic = $match[2];
  $den = $match[3];
  // Tady uz mam bezne promenne, ktere mohu normalne zpracovat
  // ...
}

V zásadě nic těžkého a dá se s tím vyjít, má to ale několik nevýhod: Za prvé, ve složitějších výrazech začne počet závorek rychle narůstat, přičemž velká část z nich bude z hlediska odkazovacích skupin zbytečná (použijete je pro funkci „podvýraz je znakem“, ne proto, že byste je chtěli dále zpracovávat). Když například rozšířím příklad s datem, že povolené jsou i tvary 2011-05 (jen rok a měsíc, za den se dosadí jednička) a 2011 (jen rok, za měsíc i den se dosadí jednička), tak se regulární výraz změní na ^([0-9]{4})(-([0-9]{2})(-([0-9]{2}))?)?$ (přibyly dvě skupiny, které používám jenom na to, abych je mohl udělat volitelnými pomocí otazníku).

Druhá nevýhoda souvisí s předchozí: Přidáním závorek mi nejenom přibyly zbytečné skupiny (dnes v době gigabajtových paměti se nad zbytečně vyplýtvanými pár kilobajty dá mávnout rukou, i když mi nad tím srdce krvácí), ale také se změnilo číslování. Sledujte otvírací kulaté závorky: rok je stále skupina č. 1, ale měsíc už není skupina č. 2 – tou je „mínus měsíc“ – ale č. 3; obdobně den se z čísla tři přesunul až na číslo pět. Tzn. nestačí, že pro vytvoření volitelného měsíce musím změnit regulární výraz (což v rozsáhlejších případech už samo o sobě není žádná legrace), ale musím projít celý kód, který s tím regulárním výrazem pracuje, a přečíslovat skupiny. A pokud nějakou z nich přehlédnu, tak potěš koště – najít tenhle typ přehlédnutí bývá extrémně náročné.

Knihovna PCRE (pozor, jiné implementace regulárních výrazů většinou už ne!) nabízí dva mechanismy pro řešení těchto problémů: „nezachycované skupiny“ a „pojmenované skupiny“. Oboje velmi rád používám.

Nezachycované skupiny

Naznačil jsem, že mnohdy vytváříme skupiny ne proto, aby se na ně dalo odkazovat, ale jen proto, aby se vytvořila část, na kterou nasadíme vhodný kvantifikátor (v příkladu s volitelným dnem a měsícem v datu to byl otazník), a že vytvoření nové odkazovací skupiny je jen vedlejším efektem společného zápisu. Mechanismus „nezachycovaných skupin“ umožňuje právě tohle řešit: udělá skupinu, kterou jde kvantifikovat, ale na kterou se nelze odkazovat (a která tudíž nezmění číslování následujících skupin). Zápis je docela jednoduchý, na začátek skupiny hned za závorku stačí napsat ?: a je hotovo. Regulární výraz s volitelným dnem a měsícem pak zapíšeme jako ^([0-9]{4})(?:-([0-9]{2})(?:-([0-9]{2}))?)?$ (změny proti původní verzi jsou zvýrazněny) a dosáhneme přesně toho, co bylo požadováno: den i měsíc jsou volitelné a jsou číslovány stejně jako v původní „nevolitelné“ verzi (rok = 1, měsíc = 2, den = 3).

V souvislosti s nezachycovanými skupinami si dejte pozor na jednu zradu: Pokud jsem něco zásadního nepřehlédl, tak toto chování je sice dokumentováno jen pro zápis (?:výraz), ale ve skutečnosti se ve všech mě známých verzích PCRE uplatňuje na všechny podskupiny, které začínají otazníkem – tzn. i na všechny „pokročilé podskupiny“ ze čtvrtého dílu!!! Abych dal příklad: Ve výrazu \bNautil(?=us\b) (ze začátku článku) se bude vyskytovat pouze skupina nula (celý nalezený výraz), přestože výskyt závorky říká, že by měla existovat i skupina 1 (text „us“ následovaný koncem slova); pokud se chcete odkazovat na „us“, potřebujete ho vložit ještě do další závorky: \bNautil(?=(us\b)) (verze \bNautil((?=us\b)) kupodivu nefunguje). Obecně doporučuji, pokud chcete používat pokročilé podskupiny, si předem ověřit, jak budou podskupiny vlastně počítány.

Pojmenované podskupiny

Nezachycované podskupiny řeší řadu problémů, neporadí si ale s případem, kdy do výrazu přidáte další „normální“ podskupinu, všechny následující se kvůli ní přečíslují a vy musíte projít celý program a přečíslovat v něm příslušné indexy. Pojmenované podskupiny dovolují skupinám vedle číslování podle pořadí přidat i jméno, na které se můžete odkazovat (tzn. k dispozici je jak jméno, tak pořadí – ale asi nemá logiku v takovém případě používat odkazování pořadím).

„Drobná“ nevýhoda pojmenovaných skupin je, že nejsou zrovna standardní součástí implementací regulárních výrazů, takže je řada implementací nezná vůbec a ostatní je zapisují každá jinak. Knihovna PCRE usnadňuje programátorovi práci aspoň v tom, že podporuje těch různých zápisů co nejvíc. Já jsem si navykl na Pythonovskou variantu, ale pokud je vám bližší, můžete používat i dotnetovou:

  • Python: (?P<název>Výraz) (např. ^(?P<ROK>[0-9]{4})-(?P<MESIC>[0-9]{2})-(?P<DEN>[0-9]{2})$)
  • .NET (varianta 1): (?<název>Výraz) (např. ^(?<ROK>[0-9]{4})-(?<MESIC>[0-9]{2})-(?<DEN>[0-9]{2})$ – za otazníkem chybí P)
  • .NET (varianta 2): (?'název'Výraz) (např. ^(?'ROK'[0-9]{4})-(?'MESIC'[0-9]{2})-(?'DEN'[0-9]{2})$ – název je uzavřen do apostrofů)

V obou případech pak budete mít k dispozici i skupiny pojmenované příslušnými názvy (v příkladech ROK, MESIC a DEN – pozor, záleží na velikosti písmen!), na které se můžete odkázat buď přímo v regulárním výrazu pojmenovanou variantou backreferencí:

  • Obyčejná backreference podle pořadí (jen pro připomenutí z třetího dílu): \pořadí (např. \bhref=(["']?).+?\1).
  • Python: (?P=název) (např. \bhref=(?P<UVOZOVKA>["']?).+?(?P=UVOZOVKA))
  • .NET (varianta 1): \k<název> (např. \bhref=(?P<UVOZOVKA>["']?).+?\k<UVOZOVKA>)
  • .NET (varianta 2): \k'název' (např. \bhref=(?P'UVOZOVKA'["']?).+?\k'UVOZOVKA')

nebo přímo v programu:

$text = '2011-05-21'; // vstupni text
$regexp = '^(?P<ROK>[0-9]{4})-(?P<MESIC>[0-9]{2})-(?P<DEN>[0-9]{2})$'; // regularni vyraz
if (preg_match('~'.$regexp.'~', $text, $match))
{
  // Pokud se dostanu sem, byl regularni vyraz v textu nalezen
  // a do pole $match mi PHP vlozilo jednotlive podskupiny.
  $rok = $match['ROK']; 
  $mesic = $match['MESIC'];
  $den = $match['DEN'];
  // Tady uz mam bezne promenne, ktere mohu normalne zpracovat
  // ...
}

(V PHP je tato syntaxe podporována pouze v PCRE variantě regulárních výrazů, proto používám preg_match místo ereg; přidání ~ na začátek a konec výrazu je dané jen způsobem zápisu regulárního výrazu v této implementaci; snad se k tomu ještě vrátím v nějakém dalším díle článku.)

Nahrazování v textu

Na konec jsem si nechal funkci nahrazování, která je uživatelům asi nejpřístupnější – stejně jako pouhé vyhledávání ji totiž mohou využít i běžní uživatelé, kteří nejsou programátory. Jako poslední je proto, že se v ní uplatní poznatky ze všech tří předchozích funkcí.

S nahrazováním už se asi většina z vás setkala v jeho základní podobě – „najdi slovo ‚Franta‘ a nahraď ho slovem ‚osel'“. Regulární výrazy umožňují v zásadě to samé, ale s tím, že hledat i nahrazovat můžete nejen slovo, ale i výraz.

Hledání a nahrazování je bohužel daleko nejméně standardizovaná část regulárních výrazů, a důsledkem je, že k tomu každá implementace přistupuje jinak – a to nejen na úrovni knihovny (PCRE používá jinou syntaxi pro nahrazování než PHP POSIX), ale i na úrovni použití jedné a téže knihovny (Programmer’s Notepad používá jinou syntaxi než RESearch ve FAR Manageru, přestože oba používají PCRE). Je dokonce zcela běžné, že konkrétní implementace neumí nahrazování s pomocí regulárních výrazů vůbec, nebo že to sice umí, ale regulární výraz může být použit jen na straně hledání (co chci nahradit), ale ne na straně nahrazení (čím to chci nahradit).

Předpokládejme, že regulární výrazy fungují na straně vyhledávání (co hledám) i na straně nahrazování (čím to nahrazuji). Vyhledávací stranu už máme dostatečně probranou z předchozích kapitol, povíme si něco o možnostech na straně nahrazování. Jsou to:

Nahrazení výrazu textem

Pro tuhle funkci vlastně ani nepotřebujeme regulární výrazy na straně hledání, protože nalezený výraz (který může být jak regulární výraz, tak prostý text) nahrazujeme vždy jedním a tím samým textem. Při úpravě e-booků třeba běžně používám nahrazení výrazu \s{2,} (2 a více po sobě jdoucích prázdných znaků, typicky mezer) znakem mezery, nebo výrazu \.{3,} (tři a více po sobě jdoucích teček) textem &hellip; (HTML zápis pro ).

Nahrazování s využitím podskupin

V nahrazovaném textu se můžou, pokud to editor umí, vyskytovat podskupiny, a to jak číslované, tak pojmenované. Například ve článku o převodu knih z TXT do HTML psal o tom, jak „obalit“ textový řádek tagem <p>, aby se z něj stal HTML odstavec: hledal jsem ^(.+)$ (neprázdný řádek, který se celý stane podskupinou) a nahrazoval jsem ho výrazem <p>$1</p> (na začátku <p>, potom první podskupina, tj. nalezený řádek, a na konci </p>).

V každém případě musíte syntaxi adaptovat na to, co který editor umožňuje. FAR Manager s pluginem RESearch umí:

  • Nahrazování číslovaných podskupin zápisem $číslo (pro skupiny 0 až 9) resp. ${číslo} (pro libovolné skupiny).
  • Nahrazování pojmenovaných podskupin zápisem ${název}.

Naproti tomu Programmer’s Notepad dokáže jen nahrazování číslovaných podskupin, a to ještě jen těch s čísly 0 až 9, zápisem \číslo (nicméně vyhledávat dokáže i skupiny pojmenované, jen se pak na to jméno neumí odkázat – nebo se mi aspoň nepodařilo najít, jak to udělat).

Další nahrazení

Některé editory umí ještě některá další nahrazení. Nakolik se dají nebo nedají počítat mezi nahrazení podle regulárních výrazů je otázka, spíš se ale přikláním k tomu je zařadit (protože se dají výhodně použít v kombinaci s regulárním nahrazováním pomocí skupin). Problém je v tom, že pokud to nějaký editor má (a že takových moc není), tak pro to má nějakou svoji speciální syntaxi, kterou nikdo jiný nezná. Proto jen několik výrazů, která používám v RESearch pluginu pro FAR Manager:

  • Začátek malých písmen (\L), začátek velkých písmen (\U), konec změny velikosti písmen (\E): Vše, co bude vloženo mezi \L (resp. \U) a \E bude převedeno na velká písmena. Pokud dám nahradit výraz \bpepak\p{L}*\b („pepak“ a všechny tvary tohoto slova) výrazem \U$0\E, převedu všechny „pepaky“ na velká písmena.
  • Číslování: číslo řádku $L, číslo řádku od začátku nahrazování $N, počet nahrazení $R (kolikáté nahrazení právě probíhá). Číslování začíná nulou, je ale možné začít od libovolného čísla s pomocí složených závorek: ${R+3} (počet nahrazení, počínaje trojkou). Hodí se to pro číslování kapitol nebo poznámek pod čarou.
  • Plus je několik dalších zápisů, např. pro zarovnávání čísel na daný počet míst; pokud vás to zajímá, nechte si zobrazit nápovědu RESearch a hledejte téma „Replacement Text“.

 

Pokud vás toto téma zajímá, doporučuji k dalšímu studio stránky Regular-Expressions.info, zejména části Replacement Syntax, Flavor-specific Syntax a Flavor Comparison.

Příště, pokud bude zájem, se trochu podívám na konkrétní implementace pro Pascal (Delphi) a PHP.

Podobné příspěvky:

3 komentáře “Regulární výrazy (6.) – další zpracování”

  1. avatar lajka napsal:

    Jojo, jen jsem jí akorát ještě nezkoušel. Při budoucím vývoji na tu novou knihovnu ale asi mrknu… Díky.

  2. avatar pepak napsal:

    Klidně můžeš použít i TPerlRegEx. Nejsem si teď z hlavy jistý, jestli i jeho „normální“ verze funguje ve starších Delphi, ale lehce upravená verze, kterou používám v YouTube Downloaderu, běží i pod Delphi 5. A za ty pokročilé vlastnosti jako pojmenované podskupiny to rozhodně stojí.

  3. avatar lajka napsal:

    Dobrej seriál.
    Já zatím používám http://delphi.cz/post/Regularni-vyrazy-TRegExpr.aspx , protože zatím nehodlám opustit Delphi 2006, ale Delphi XE už má podporu PCRE konečně nativně, takže už to konečně není potřeba řešit knihovnou.
    Co se týče PHP, pěknej nástin je použit v příručce Jakuba Vrány – 1001 tipů a triků v PHP.
    A ohledně rodnýho čísla to je ještě zamotanější a s výjimkama:
    http://lorenc.info/3MA381/overeni-spravnosti-rodneho-cisla.htm

Leave a Reply

Themocracy iconWordPress Themes

css.php