Categories: Regulární výrazy

Regulární výrazy a JavaScript (4) – metody test() a exec()

Pro práci s regulárními výrazy disponuje objekt RegExp těmito metodami:

  • test() – zjistí, zda řetězec či alespoň jeho část odpovídá regulárnímu výrazu
  • exec() – najde a vrátí část řetězce odpovídající regulárnímu výrazu (a případně jednotlivým subvýrazům)

Instance objektu RegExp mají tyto vlastnosti:

  • source – zdrojový text regulárního výrazu
  • global – zda je použit modifikátor g (boolean hodnota)
  • ignoreCase – zda je použit modifikátor i (boolean hodnota)
  • multiline – zda je použit modifikátor m (boolean hodnota)
  • lastIndex – pozice za posledním znakem poslední shody (má smysl při použití modifikátoru g)

Výše uvedené vlastnosti jsou vlastností instance objektu RegExp až od verze JavaScriptu 1.5. Dříve byly přímo vlastností třidy RegExp (což je docela nelogické).

Zapisujeme ve tvaru regexp.test(řetězec), kde regexp je regulární výraz, kterému má odpovídat řezětec. Funkce vrací hodnotu true, pokud v řetězci byla nalezena shoda s regexpem, jinak vrací false.

//test() – příklad 1

var str=“15 USD, 10 EUR, 300 CZK“;

var re1=/(\d+)\s(\w+)/;

var result1=re1.test(str); //vrací: true

alert(„Výsledek: „+result1);

V prvním příkladu není použit modifikátor g a tak se po nalezení shody (15 USD) v dalším hledání možných shod nepokračuje a funkce vrátí true.

Pokud je nastaven modifikátor g, provede se globální vyhledávání. To v praxi znamená, že ve vlastnosti lastIndex se zapamatuje pozice v řetězci, která následuje po posledním znaku předchozí shody. Tuto poněkud krkolomnou větu snadno pochopíme na následujícím příkladu:

//test() – příklad 2

var str=“15 USD, 10 EUR, 300 CZK“;

var re2=/(\d+)\s(\w+)/g;

var result2;

var i=0; //inicializace – počet nalezených shod

while(result2=re2.test(str))

{

i++; //inkrementace počtu nalezených shod

alert(„Pocet nalezenych: „+i+“\nDalsi hledani od pozice: „+re2.lastIndex);

};

V tomto příkladu je nastaven modifikátor g. Metoda test() i v tomto případě vrací pouze hodnoty true a false. Rozdíl je ovšem v tom, že vyhledávání nezačíná vždy od prvního znaku řetězce (jako je tomu u neglobálního vyhledávání), ale od pozice určené vlastností regulárního výrazu (v našem příkladu result2) lastIndex. V případě, že byly nalezeny všechny shody, nastaví se vlastnost lastIndex na 0 (nastavení lastIndex na nulu můžeme provést i explicitně, pokud chceme zajistit vyhledávání od začátku řetězce, i když ještě nebyly nalezeny všechny shody).

Chceme-li tedy zjistit pomocí metody test() počet shod regulárního výrazu s řetězcem, můžeme provést volání v cyklu a při každém vrácení hodnoty true inkrementovat nějaké vlastní počítadlo (v našem příkladu proměnná i). V našem cyklu (kromě inkrementace tohoto počítadla a zobrazení jeho hodnoty) navíc zobrazujeme aktuální hodnotu vlastnosti lastIndex.

Zapisujeme ve tvaru regexp.exec(řetězec), kde regexp je regulární výraz, kterému má odpovídat řetězec. V případě shody vrací metoda pole, které obsahuje pod indexem 0 řetězec odpovídající celému regexpu a v dalších prvcích pole shody s jednotlivými subvýrazy regulárního výrazu (tedy vrací stejné pole jako metoda match() objektu String při neglobálním vyhledávání).

Kromě toho má navrácené pole dvě objektové vlastnosti – index a input. Vlastnost index obsahuje informaci o pozici, na níž začíná shoda. Vlastnost input obsahuje řetězec, v němž je vyhledáváno. V případě nenalezení shody vrací metoda null.

Rozdíl mezi metodou exec() a dříve zmíněnou metodou match() je v tom, že exec() vrací pouze první shodu i v tom případě, že je použito globální vyhledávání (použit modifikátor g). Chování metody exec() je na druhou stranu podobné výše zmíněné metodě test(). Podobnost tkví ve využívání vlastnosti lastIndex (při globálním vyhledávání) pro uchování informace o pozici, od níž se má pokračovat v prohledávání řetězce. Vše nejlépe uvidíme na příkladu:

//exec() – příklad 1

var str=“15 USD, 10 EUR, 300 CZK“;

var re1=/(\d+)\s(\w+)/g;

var i=0; //inicializace – počet nalezených shod

var subvyrazy; //řetězec pro zapamatování subvýrazů

while(result1=re1.exec(str))

{

i++; //inkrementace počtu nalezených shod

subvyrazy=““;

for(var j=1;result1[j];j++)

subvyrazy=subvyrazy+“\n[„+j+“]: „+result1[j];

alert(„Vyhledava se v retezci: „+result1.input

+“\nNalezena shoda:“+result1[0]

+“\nShoda zacina na pozici: „+result1.index

+“\nPocet doposud nalezenych: „+i

+“\nDalsi hledani od pozice: „+re1.lastIndex

+“\n\nShody se subvyrazy:“+subvyrazy);

};

V cyklu while voláme opakovaně re1.exec(str) (podobně, jako jsme volali ve výše uvedeném příkladu metodu test()). Tento cyklus se zastaví až v okamžiku, kdy nebude nalezena další shoda a volání re1.exec(str) vrátí null (což se zkonvertuje na false). Cyklus for pak slouží pouze k procházení shod s jednotlivými subvýrazy (jak víme, řetězec odpovídající prvnímu subvýrazu bude v prvku pole s indexem 1, proto proměnnou j inicializujeme na hodnotu 1) a jejich zapsání do řetězce subvyrazy (kvůli následnému zobrazení pomocí alert()).

Funkce alert() tak pro každou shodu zobrazí celý řetězec v němž se vyhledává (result1.input), shodu – tedy část řetězce odpovídající celému regulárnímu výrazu (result1[0]), pozici v řetězci, kde začíná shoda (result1.index), „naše interní“ počítadlo shod (i), pozici v řetězci, od níž začne další vyhledávání (re1.lastIndex), a nakonec naši proměnnou subvyrazy.

Závěrem ještě malá poznámka. Výše uvedené příklady (příklad 2 u metody test() a příklad 1 u metody exec()) budou korektně fungovat pouze za předpokladu použití modifikátoru g. V případě jeho nepoužití je vždy vyhledáváno od začátku řetězce. Podmínka while je tedy splněna vždy, pokud je v řetězci alespoň jedna shoda. Cyklus se tak stane nekonečnou smyčkou. Řešení nezávislé na (ne)použití modifikátoru g si ukážeme jindy.

Ačkoliv má JavaScript ve verzi 1.5 docela slušnou podporu Perl-compatible regulárních výrazů, na některé věci si musíme nechat zajít chuť. V čem se tedy liší funkčnost regulárních výrazů v JavaScriptu oproti PHP?

  • Vždy (bez ohledu na modifikátor multiple-lines) platné hranice pro začátek a konec řetězce (v PHP \A a \Z).
  • Modifikátory „single-line“ (změna chování metaznaku tečka).
  • Modifikátor „extended“ (komentáře v regulárním výrazu a ignorování bílých znaků).
  • Modifikátor „ungreedy“ (globální zapnutí líného chování všech nenasytných kvantifikátorů).
  • Komentáře.
  • Pojmenované subvýrazy (možnost odkazovat se zvoleným názvem místo číslem).
  • Tvrzení o předcházejícím.
  • Podmíněné subvýrazy.
  • Reference na text předcházející textu, který vytváří shodu s regulárním výrazem ($`).
  • Reference na text následující za textem, který vytváří shodu s regulárním výrazem ($').
  • Výsledku, který nám v PHP zajistí funkce preg_match_all(), můžeme v JavaScriptu dosáhnout použitím RegExp metody exec() v cyklu (viz příklad výše).
  • Funkčnost, kterou v PHP zajišťuje funkce preg_replace_callback(), v JavaScriptu obsahuje přímo String metoda replace() (viz čtvrtý příklad uvedený u popisu metody replace() v předchozím článku).

Veškeré zde uvedené příklady si můžete stáhnout a otestovat přímo ve svých prohlížečích, samozřejmě jen v případě, že podporují JavaScript a regulární výrazy.

Tento článek byl původně publikován na serveru Interval.cz, kde naleznete
originální verzi článku.
Miroslav Pecka

Share
Published by
Miroslav Pecka

Recent Posts

GA4 (not set) problém & jeho řešení

Jak se zbavit (not set) v Session Source a Session Medium?

2 roky ago

Měření QR kódů a offline zdrojů do Google Analytics

Chcete doměřit efekt vaší offline reklamy, ze které vedete lidi na váš web? Jde to…

2 roky ago

5+1 věcí, které se online markeťák může naučit od ajťáka

Tenhle článek jsem měl rozepsaný fakt dlouho, ale je stále aktuální… Trápí mě, že opakovaně…

4 roky ago

Profesionál v onlinu: řemeslo + kontext + přesahy

Poslední dobou jsem se setkal s pár majiteli malých firem, kteří mají web a snaží…

4 roky ago

Nástroje pro tvorbu screencast videí

Občas se mě někdo ptá, co používám pro tvorbu screencastů a online videí. Které nástroje…

4 roky ago

7 Google Analytics video návodů pro efektivnější práci

V rámci 5 videí najdete 7 krátkých video tipů pro zefektivnění práce s Google Analytics…

5 roky ago