Koncepce série
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.
Co jsou to regulární výrazy?
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ů:
- POSIX
- Perl-compatible
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 regulárních výrazů v JavaScriptu
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.
Tvoříme regulární výrazy
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:
Zpětné lomítko, tečka
\ | 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:
- Pokud chceme vytvořit regulární výraz, kterému bude odpovídat řetězec
2*3=6
, musíme použít regulární výraz2\*3=6
(protože*
je metaznakem). - Regulárnímu výrazu
a.b
budou odpovídat řetězceaab
,abb
,aZb
a podobně.
Nenasytné kvantifikátory
? | 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) |
Líné kvantifikátory
?? | 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.
Znaky zapisované pomocí escape sekvencí
\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 |
Skupiny znaků
[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:
- regulárnímu výrazu
[ab]{2,5}
bude odpovídat 2-5 znaků dlouhý řetězec tvořený pomocí znakůa
ab
, například tedyab
,abbaa
,aaa
,bbbb
- regulárnímu výrazu
[1-5]+
bude odpovídat číslo tvořené minimálně jednou číslicí, přičemž povolené číslice jsou pouze1
,2
,3
,4
,5
- regulárnímu výrazu
\d{4}
bude odpovídat sekvence právě čtyř číslic desítkové soustavy, například1289
či0054
(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) - regulárnímu výrazu
\w{6}
bude odpovídat sekvence právě šesti znaků (alfanumerické znaky doplněné o znak podtržítka), napříkladAdam84
čijan_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)
Hranice – aneb ukotvení (částí) řetězců
^ | 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:
- regulárnímu výrazu
^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 - regulárnímu výrazu
\d{4}0$
odpovídají pěticiferná čísla (respektive spíše sekvence číslic) končící nulou, která jsou na konci řetězce či řádku
Podrobně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ší).
Další konstrukce
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:
- Regulárnímu výrazu
ahoj|nazdar
odpovídá právě jedna z možností pozdravu (tedy řetězecahoj
nebo řetězecnazdar
). - Regulárnímu výrazu
(\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ězce050
,868
či222
, ale již ne123
. - Regulárnímu výrazu
(?:ab)+
bude vyhovovat minimálně dvouznakový řetězec složený z (nepovinně se opakující) sekvence znakůab
; například tedyab
,abab
,ababab
, ale již neababa
. ( )
Odkazy a zdroje
- Core JavaScript Guide 1.5: Regular Expressions
- Core JavaScript Reference 1.5: RegExp object
- RegExLib.com – databáze regulárních výrazů, on-line tester
- Regular-expressions.info – tutoriál, příklady, programy pro práci s regulárními výrazy
- Regular Expressions for JS – a free online quick reference – elegantní shrnutí regulárních výrazů v JS
- Regulární výrazy – český portál o regulárních výrazech (testery, kategorizované odkazy, diskusní fórum)
originální verzi článku.
Nenech si to pro sebe...
Pokud tě článek zaujal, sdílej ho s ostatními. Díky!