Regulární výrazy a JavaScript – metody test() a exec()
Metody String objektů používajících regulární výrazy jako svůj argument jsme si ukázali v předchozích dvou článcích. V tomto článku se budeme věnovat metodám RegExp objektů. V závěru se také podíváme na malé srovnání práce s regulárními výrazy v JavaScriptu a PHP.
Metody a vlastnosti objektu RegExp
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ýrazuexec()
– 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ýrazuglobal
– zda je použit modifikátorg
(boolean hodnota)ignoreCase
– zda je použit modifikátori
(boolean hodnota)multiline
– zda je použit modifikátorm
(boolean hodnota)lastIndex
– pozice za posledním znakem poslední shody (má smysl při použití modifikátorug
)
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é).
test()
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
.
exec()
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.
Co JavaScript nepodporuje a jiné odlišnosti
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?
Co JavaScript nepodporuje
- 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.
Co má JavaScript navíc
- 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 (
$'
).
Odlišnosti ve funkcích pro práci s regulárními výrazy
- Výsledku, který nám v PHP zajistí funkce
preg_match_all()
, můžeme v JavaScriptu dosáhnout použitímRegExp
metodyexec()
v cyklu (viz příklad výše). - Funkčnost, kterou v PHP zajišťuje funkce
preg_replace_callback()
, v JavaScriptu obsahuje přímoString
metodareplace()
(viz čtvrtý příklad uvedený u popisu metodyreplace()
v předchozím článku).
Ke stažení
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.
Mohlo by vás také zajímat
-
Jak zvýšit CTR vašeho e-mail marketingu
9. září 2024 -
AI v programování: Jak používat GitHub Copilot (část 1)
12. února 2024
Nejnovější
-
Doména .io v ohrožení: Co přinese předání Čagoských ostrovů?
10. října 2024 -
Jak se chránit před podvody na internetu – část 1
8. října 2024