Pravděpodobně mnozí z vás znají použití zástupných znaků „*“ a „?“, například při vyhledávání souborů. Jistě uznáte, že použití takových zástupných znaků (wildcards) je často neocenitelné, přesto nemusí být dostačující, pokud chceme postihnout komplikovanější řetězec. Právě k tomu se nám mohou hodit regulární výrazy.
Mnohým z vás je možná výše uvedený text povědomý. Není divu. Úvodní odstavec jsem si dovolil převzít z prvního článku série Perl-compatible regulární výrazy v PHP, který vycházel před nedávnem na Intervalu. Když jsem se proto rozhodl napsat také několik článků o regulárních výrazech v JavaScriptu, stál jsem před rozhodnutím, zda tuto sérii koncipovat zcela stejně (tedy popisovat kompletní problematiku regulárních výrazů a jejich aplikaci v příslušném programovacím jazyce) nebo předpokládat znalost tvorby regulárních výrazů a omezit se jen na popis prostředků pro práci s regulárními výrazy v JavaScriptu. Rozhodl jsem se pro kompromis.
Úvodem se podíváme na konstrukce regulárních výrazů (ovšem již mnohem stručněji, proto začátečníkům v práci s regulárními výrazy doporučuji nejdříve si přečíst články
Perl-compatible regulární výrazy v PHP – základní konstrukce a Perl-compatible regulární výrazy v PHP – praktické příklady) a v dalších článcích se již budu věnovat jednotlivým metodám (funkcím) pro práci s regulárními výrazy. Vzhledem ke skutečnosti, že část věnující se samotným regulárním výrazům bude spíše shrnutím problematiky než jejím vysvětlováním, v příslušných místech se budu odkazovat na podrobnější vysvětlení příslušného tématu v článcích o perl-compatible regulárních výrazech v PHP.
Protože česká (a do značné míry ani anglická) terminologie týkající se regulárních výrazů není jednotná, budu se držet názvosloví, které jsem používal v předchozích textech.
Regulární výrazy jsou speciální textové řetězce, které popisují určitou masku (vzor), které má odpovídat určitý textový řetězec.
Nejlépe bude, když předcházející větu vysvětlím na příkladu. Řekněme, že máme soubor s textem, kde na každém řádku je nějaké křestní jméno, a naším úkolem je najít jména začínající na „P“, která jsou delší než pět písmen. Pro takové zadání (řetězec začíná na „P“ a zároveň je delší než pět znaků) vytvoříme příslušný regulární výraz. Takový regulární výraz se pak porovná postupně s každým řádkem a řádky, kde došlo ke shodě regulárního výrazu s příslušným textem na řádku, mohou být vráceny jako výsledek. Vráceny tak budou řádky se jmény Pankrác, Patricie, Patrik, Pavlína a podobně, ale již ne Petr, Pavel, Petra či Ondřej, Daniel a jiné.
Regulární výrazy se používají v mnoha programovacích jazycích (Perl, Java, C#, Javascript, PHP a další). Běžně je možné se setkat s dvěma typy regulárních výrazů:
Regulární výrazy používané v JavaScriptu vycházejí z Perlu a tak jejich syntaxe je perlovským výrazům (či perl-compatible regulárním výrazům používaným v PHP) velmi podobná. Některé vlastnosti regulárních výrazů (tvrzení o předcházejícím, komentáře, podmíněné subvýrazy a podobně) však budeme muset v JavaScriptu oželet.
Implementace práce s regulárními výrazy je v různých verzích JavaScriptu různá. Verze 1.1 a nižší nepodporují regulární výrazy vůbec. Od verze 1.2 je zavedena podpora regulárních výrazů, verze 1.3 přidala objektu RegExp
metodu toSource
, od verze 1.5 je zaveden „multiple lines“ modifikátor, líné kvantifikátory, závorky netvořící zpětné reference a tvrzení o následujícím. V následujícím textu (nebude-li uvedeno jinak) budeme předpokládat verzi 1.5, která by měla být podporována Microsoft Internet Explorerem 6 a vyšším (respektive funkčnost implementované verze JScriptu by měla zhruba odpovídat JavaScriptu 1.5) a Gecko-based prohlížeči (Mozilla, Firefox, Netscape 6 a vyšší). Stručné shrnutí podpory jednotlivých verzí JavaScriptu v prohlížečích najdete například na stránce Geekpedia – Programming tutorial: An introduction to JavaScript.
Jak již bylo zmíněno, regulární výrazy jsou textové řetězce. Některé znaky však plní v textovém řetězci speciální funkci – takové znaky označujeme jako metaznaky. Jsou to \
, ^
, $
, .
, [
, ]
, |
, (
, )
, ?
, *
, +
, {
, }
. Pokud chceme použít metaznak v jeho původním významu, je třeba před něj doplnit zpětné lomítko \
. Takže pokud chceme hledat například řetězce obsahující a+b
, musíme použít regulární výraz a\+b
.
Shrňme si nyní použití metaznaků při konstruování regulárních výrazů v několika přehledových tabulkách:
\ | vrací metaznaku jeho původní význam při použití v regulárním výrazu |
. (tečka) | zastupuje jeden libovolný znak (kromě znaku nového řádku) |
Malý příklad:
2*3=6
, musíme použít regulární výraz 2\*3=6
(protože *
je metaznakem).a.b
budou odpovídat řetězce aab
, abb
, aZb
a podobně.? | minimálně 0krát, maximálně 1krát |
* | minimálně 0krát (maximálně neomezeno) |
+ | minimálně 1krát (maximálně neomezeno) |
{n} | právě nkrát |
{m,n} | minimálně mkrát, maximálně nkrát |
{m,} | minimálně mkrát (maximálně neomezeno) |
?? | minimálně 0krát, maximálně 1krát |
*? | minimálně 0krát (maximálně neomezeno) |
+? | minimálně 1krát (maximálně neomezeno) |
{m,n}? | minimálně mkrát, maximálně nkrát |
{m,}? | minimálně mkrát (maximálně neomezeno) |
Malý příklad:
Nenasytné a líné kvantifikátory se liší následovně. Pokud máme řetězec aaa
a regulární výraz a+
, regulárnímu výrazu bude odpovídat aaa
– nenasytné chování. Pokud máme stejný řetězec aaa
, ale porovnáme jej s výrazem a+?
, výsledkem bude jen a
– líné chování. Podrobnější (a názornější) vysvětlení rozdílu líných a nenasytných kvantifikátorů naleznete v článku Perl-compatible regulární výrazy v PHP – modifikátory a líné kvantifikátory.
\0 | NUL znak |
\t | tabulátor |
\n | line feed (nový řádek) |
\v | vertikální tabulátor |
\f | form feed |
\r | carriage return |
\xnn | znak zadaný dvouciferným hexadecimálním číslem (ASCII) |
\unnnn | znak zadaný čtyřciferným hexadecimálním číslem (Unicode) |
\cX | řídící znak (control character); X je z rozsahu A-Z; například \cK je control-K |
[abc] | skupina znaků daná výčtem znaků (v tomto případě abc ) |
[a-z] | skupina znaků daná intervalem (v tomto případě a-z ) |
[^abc] | doplněk skupiny znaků dané výčtem znaků (v tomto případě jakýkoliv znak kromě abc ) |
[^a-z] | doplněk skupiny znaků dané intervalem (v tomto případě jakýkoliv znak kromě znaků z intervalu a-z ) |
\d | číslice 0-9 |
\D | jakýkoliv znak kromě číslic 0-9 |
\w | znaky „slova“ (ekvivalentní zápisu a-zA-Z0-9_) |
\W | jakýkoliv znak kromě znaků „slova“ (ekvivalentní zápisu ^a-zA-Z0-9_) |
\s | „bílé“ znaky (ekvivalentní zápisu \f\n\r\t\v\u00A0\u2028\u2029 ) |
\S | jakýkoliv znak kromě „bílých“ znaků (ekvivalentní zápisu ^ \f\n\r\t\v \u00A0\u2028\u2029 ) |
Malý příklad:
[ab]{2,5}
bude odpovídat 2-5 znaků dlouhý řetězec tvořený pomocí znaků a
a b
, například tedy ab
, abbaa
, aaa
, bbbb
[1-5]+
bude odpovídat číslo tvořené minimálně jednou číslicí, přičemž povolené číslice jsou pouze 1
, 2
, 3
, 4
, 5
\d{4}
bude odpovídat sekvence právě čtyř číslic desítkové soustavy, například 1289
či 0054
(takový regulární výraz bychom mohli například použit při kontrole správnosti, respektive smysluplnosti zadání nějakého PIN kódu)\w{6}
bude odpovídat sekvence právě šesti znaků (alfanumerické znaky doplněné o znak podtržítka), například Adam84
či jan_novak
(takový regulární výraz bychom mohli například použit při kontrole správnosti, respektive smysluplnosti zadání přihlašovacího jména do nějakého systému)^ | začátek řetězce nebo řádku |
$ | konec řetězce nebo řádku |
\b | hranice „slova“ |
\B | jakákoli pozice, kromě pozic, které jsou hranicí „slova“ |
Malý příklad:
^1\d{3}
odpovídají čtyřciferná čísla (respektive spíše sekvence číslic) začínající jedničkou, která jsou na začátku řetězce či řádku\d{4}0$
odpovídají pěticiferná čísla (respektive spíše sekvence číslic) končící nulou, která jsou na konci řetězce či řádkuPodrobnější popis problematiky hranic (takzvaných shod nulové délky) naleznete v článku Perl-compatible regulární výrazy v PHP – hranice (pozor však na to, že v PHP je množina hranic větší).
a|b | alternativy – rozdělení výrazu na dvě části (a a b ), přičemž dojde-li ke shodě alespoň s jednou částí výrazu, uvažuje se, že řetězec regulárnímu výrazu odpovídá |
(x) | subvýraz – řetězec odpovídající části výrazu (x ) (subvýrazu) ohraničené kulatými závorkami je zapamatován pro pozdější použití (zpětná reference) |
(?:x) | uzávorkování netvořící zpětné reference – výraz v závorce (x ) je vyhodnocen, ale řetězec odpovídající této části výrazu není zapamatován |
\n | zpětná reference – de facto zastupuje řetězec odpovídající příslušnému subvýrazu; n je číslo subvýrazu |
a(?=b) | pozitivní tvrzení o následujícím (viz článek Perl-compatible regulární výrazy v PHP – lokální modifikátory, tvrzení) |
a(?!b) | negativní tvrzení o následujícím (viz článek Perl-compatible regulární výrazy v PHP – lokální modifikátory, tvrzení) |
Malý příklad:
ahoj|nazdar
odpovídá právě jedna z možností pozdravu (tedy řetězec ahoj
nebo řetězec nazdar
).(\d)\d\1
odpovídá sekvence tří číslic, přičemž první a poslední číslice musí být shodné (zpětná reference se totiž odkazuje na první znak řetězce); vyhovovat tak budou například řetězce 050
, 868
či 222
, ale již ne 123
.(?:ab)+
bude vyhovovat minimálně dvouznakový řetězec složený z (nepovinně se opakující) sekvence znaků ab
; například tedy ab
, abab
, ababab
, ale již ne ababa
. ( )Jak se zbavit (not set) v Session Source a Session Medium?
Chcete doměřit efekt vaší offline reklamy, ze které vedete lidi na váš web? Jde to…
Tenhle článek jsem měl rozepsaný fakt dlouho, ale je stále aktuální… Trápí mě, že opakovaně…
Poslední dobou jsem se setkal s pár majiteli malých firem, kteří mají web a snaží…
Občas se mě někdo ptá, co používám pro tvorbu screencastů a online videí. Které nástroje…
V rámci 5 videí najdete 7 krátkých video tipů pro zefektivnění práce s Google Analytics…