Bez regulárních výrazů se dnes programátoři neobejdou a je dobré seznámit se s jejich možnostmi i v JavaScriptu. Článek obsahuje test vašich znalostí.

Příklady uvedené ve článku byly 16. 3. 2012 aktualizovány.

V JavaScriptu se regulární výraz dá vytvořit dvěma způsoby:

var re1 = /Regular Expression/i;
var re2 = new RegExp("Regular Expression","i");

První způsob je jednodušší, ale neumožňuje uvnitř RE použít proměnnou. Vyhodnocování RE lze ovlivnit připojením modifikátorů. Např. modifikátor i způsobí, že se nebudou rozlišovat malá a velká písmena.

Testování výskytu

Ke zjištění, zda se v určitém řetězci nachází podřetězec odpovídající danému RE, ideálně poslouží metoda test() objektu RegExp. Jejím argumentem je testovaný řetězec. Vrací hodnotu typu boolean. První příklad, tělo návratové funkce volané při pokusu o odeslání formuláře, slouží ke kontrole správného tvaru e-mailové adresy.

var str = document.forms[0].elements[0].value; // vložená hodnota předpokládaného elementu input
var vzor = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]){2,3}$/;
var isEmail = vzor.test(str);
return isEmail;

Hledání pozice výskytu

Metoda search() objektu String zjišťuje, kde v řetězci se nalézá podřetězec odpovídající danému RE, kterýžto má za argument. Vrací index pozice prvního výskytu hledaného podřetězce. Jestliže ten nalezen není, vrací -1. Jedná se tedy o obdobu metody indexOf(). V následujícím příkladu je použita pro bližší určení místa pravopisné chyby.

var veta = "Zlodějky b_l_ chyceny, když kradl_ obraz_.";
var znamka = null;
var pozice_chyby, hlaska;
do {
  veta = window.prompt("Doplňte: ", veta);
  if (veta == "Zlodějky byly chyceny, když kradly obrazy.") {
    znamka = 1;
    hlaska = "Výborně";
    }
  else {
    pozice_chyby = veta.search(/[i_]/); //!!!
    hlaska = (pozice_chyby > -1)? "Chyba u " + ++pozice_chyby + ". znaku" : "Špatně";
    }
  window.alert(hlaska);
}
while (!znamka);

Náhrady a ošetření uživatelského vstupu

Má-li být jako součást RE použit uživatelský vstup, je nutné pamatovat na to, že by mohl obsahovat speciální znaky (+, ?, [, \, . aj.), a tuto eventualitu ošetřit, aby sestavený RE byl korektní a fungoval zamýšleným způsobem! Řešení je jednoduché: před každý případný speciální znak z uživatelského vstupu se vsune obrácené lomítko (\), tím inkriminovaný znak pozbude svého zvláštního významu. Splnění tohoto úkolu dokonale zajistí metoda replace() objektu String, které se předávají dva argumenty – tím prvním je RE, tím druhým náhradní podřetězec. Vrací změněný řetězec. Celé to vypadá takhle:

var str = document.forms[0].elements[0].value; // vložená hodnota předpokládaného elementu input
str = str.replace(/(["\\\|\[\]\^\*\+\?\.\$\(\)\{\}])/g, "\\$1"); // ošetření daného uživatelského vstupu
var re = new RegExp(str,"i");

Poznámka k příkladu: výraz $1 uvedený v druhém argumentu reprezentuje shodu s tou částí RE, která je uzavřena v kulatých závorkách.

Získání podřetězce

Jak extrahovat z řetězce nějakou jeho specifickou část? Způsobů je více, ale nejsnadněji se to obvykle zvládne prostřednictvím metody exec() objektu RegExp nebo metody match() objektu String. Není-li nalezen kýžený podřetězec, vracejí null, jinak vracejí pole, jehož prvním prvkem je podřetězec odpovídající celému RE a případnými dalšími prvky jsou podřetězce shodné s jednotlivými podvýrazy (podvýrazy jsou v RE vyznačeny kulatými závorkami).

Zvlšť efektivního uplatnění dosáhnou tyto metody v případech, kdy je cílem získat jenom určitou součást hledaného podřetězce, například jen číselnou hodnotu z ceny zboží. Provedou totiž de facto dva úkoly najednou. V daném příkladě za prvé: naleznou cenovou položku, za druhé: oddělí číslo od měny.

var product = sessionStorage.cenovaBomba;
var price = product.match(/(\d+),- Kč/);
alert("Kupte to teď. Příště to bude stát "+price[1]*1.5+",- Kč!");

Rozdělení řetězce

Metoda split() objektu String vytvoří pole řetězců z řetězce, který rozdělí. Jako oddělovač slouží RE, předaný metodě formou argumentu. Oddělovače nejsou do prvků pole zahrnuty, slouží jenom pro rozpoznání konce a začátku jednotlivých položek. Opět jeden malý příklad:

var vyzva = window.prompt("Jaké jsou tvé oblíbené sporty");
var sporty = (vyzva)? vyzva.split(/,\s?/) : "";
var pocet = sporty.length;
while (pocet--) {
  navrh = window.confirm("Zahraješ si se mnou "+sporty[pocet]+"?");
  if (navrh) break;
}

Test na regulární výrazy

Programátorům webových aplikací jsou regulární výrazy užitečné zejména při validaci (ověřování formální správnosti) vstupních dat, neboť umožňují výrazně snížit množství přijatých údajů nevhodného tvaru. Jde s nimi například zjistit, jestli hodnota zadaná do textového pole začíná alespoň třemi písmeny a podobné věci. O tom, jak vypadají, už bylo napsáno dost, bohužel fakt je ten, že se dají naučit jen praxí. K praktickému pochopení regulárních výrazů snad přispěje i slíbený testík.

9 Příspěvků v diskuzi

  1. Ano, přesně tak. Zadanému výrazu neodpovídá žádné z nabízených řešení. Předpokládám, že výraz měl být (999){3}, popřípadě chyták 999{3,}.

  2. Shark -> Proč si myslíte, že řetězec „999999999“ nevyhoví RE „999{3}“? Já myslím, že je to v pořádku.

  3. V příkladu 7 se hledá podřetězec (sic!) složený z pěti devítek. Jedna z možností obsahuje pět (a více) devítek.
    Aby byl příklad opravdu špatně, muselo by se na začátek RE přidat ^ a na konec $, pak by se teprve hledala (a nenalezla) shoda s celým řetězcem.

  4. Sakra, máte pravdu. Ani nevím proč jsem měl najednou u příkladu 7 pocit, že výrazu musí odpovídat celý řetězec.

Odpovědět