Deprecated: Function set_magic_quotes_runtime() is deprecated in /mnt/data/accounts/w/webmark/data/www/blog/textpattern/lib/txplib_db.php on line 14
Regulární výrazy a JavaScript (2) - metody search() a replace() :: Blog v pavučině
Blog v pavučině je mrtev. Ať žije nový blog Všeho s Mírou
Skočit na obsah Skočit na menu Skočit na vyhledávání

Regulární výrazy a JavaScript (2) - metody search() a replace()

V předchozím článku jsme si stručně zopakovali obecné konstrukce regulárních výrazů a tak se nyní můžeme směle pustit do postupů a metod používajících regulární výrazy přímo v JavaScriptu.

Pro regulární výrazy existuje v JavaScriptu zvláštní objektový typ RegExp. Existují v zásadě dvě možnosti práce s regulárními výrazy:

  1. Použití metod objektu String, kterým jako argument předáme regulární výraz, jehož shodu s řetězcem (String) chceme testovat.
  2. Použití metod objektu RegExp, kterým jako argument předáme řetězec, jehož shodu s regulárním výrazem chceme testovat.

Regulární výraz můžeme vytvořit dvěma způsoby:

  1. jako literál: var re=/regexp/ nebo var re=/regexp/modifikátory
  2. pomocí konstruktoru objektu: var re=new RegExp("regexp") nebo var re=new RegExp("regexp","modifikátory")

V obou případech regexp představuje příslušný regulární výraz a modifikátory představuje nepovinně zadané modifikátory. (V kontextu JavaScriptu se v anglicky psaných materiálech setkáme s označením "flag", což by se spíše mělo překládat jako "příznak", ale pro zachování konzistence s texty o regulárních výrazech v PHP budu i zde používat označení "modifikátor".)

V případě zápisu regulárního výrazu coby literálu je tento z obou stran uzavřen takzvanými oddělovači. V JavaScriptu jsou jediným povoleným oddělovačem lomítka (/). V případě vytváření regulárního výrazu pomocí konstruktoru objektu RegExp nesmíme zapomenout všechny výskyty zpětného lomítka doplnit ještě o jedno zpětné lomítko. Chceme-li tak vytvořit například regulární výraz, kterému odpovídá sekvence čtyř číslic, musíme použít zápis var re=new RegExp("\\d{4}").

Přečetli jste si předcházející odstavce a stále čekáte na vysvětlení oněch "modifikátorů"? Modifikátory jsou příznaky, které určitým způsobem ovlivňují vyhodnocování regulárního výrazu. V JavaScriptu existují tři modifikátory:

  • i (ignore case) - způsobí nerozlišování malých a velkých písmen při porovnávání řetězce s regulárním výrazem; regulárnímu výrazu /ahoj/i tak budou odpovídat řetězce ahoj, Ahoj i aHoJ a další
  • g (global search) - způsobí, že i když ve vstupním řetězci bude již nalezen jeden podřetězec odpovídající regulárnímu výrazu, hledání shody bude pokračovat dále ve zbytku řetězce; máme-li například text těla e-mailu obsahující mnoho e-mailových adres a chceme vyhledat či extrahovat všechny tyto adresy, pak použijeme právě modifikátor g)
  • m (multiple lines) - způsobí, že dojde ke shodě kotvy ^ i na začátku každého řádku a ke shodě kotvy $ i na konci každého řádku (standardně dochází ke shodě jen na začátku, respektive na konci řetězce)

Všechny modifikátory lze kombinovat, přičemž na jejich pořadí nezáleží. Zápis /ahoj/ig je tak zcela ekvivalentní zápisu /ahoj/gi.

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

  • search() - zjistí, zda řetězec či alespoň jeho část odpovídá regulárnímu výrazu
  • replace() - nahradí řetězec (nebo jeho část) odpovídající regulárnímu výrazu jiným zadaným řetězcem
  • match() - najde a vrátí část nebo části řetězce odpovídající regulárnímu výrazu
  • split() - rozdělí řetězec na části; oddělovačem je řetězec odpovídající regulárnímu výrazu

Níže si probereme první dvě ze zde uváděných metod. Metodám match() a split() věnujeme samostatný článek.

Zapisujeme ve tvaru řetězec.search(regexp), kde řetězec je text, který testujeme na shodu s regulárním výrazem regexp.

Funkce vrací pozici znaku v řetězci, kde začíná část řetězce, která odpovídá regulárnímu výrazu (takovou část řetězce budeme označovat jako "shoda"). Pokud není žádná shoda nalezena, vrací -1. Vše bude zřejmé z malého příkladu, který si můžete sami vyzkoušet.

//search() - příklad 1

//přímý zápis
var result0="Interval".search(/val/); //vrací: 5
alert("Nalezeno na pozici: "+result0+" (přímý zápis)");

//vytvoření a použití proměnných (RegExp vytvářen jako literál)
var str1="Interval";
var re1=/val/;
var result1=str1.search(re1); //vrací: 5
alert("Nalezeno na pozici: "+result1+" (s použitím proměnných)");

//vytvoření a použití proměnných (RegExp vytvářen jako objekt)
var str2="Interval";
var re2=new RegExp("val");
var result2=str2.search(re2); //vrací: 5
alert("Nalezeno na pozici: "+result1+" (s použitím proměnných podruhé)");

V ukázce jsou demonstrovány tři postupy vedoucí ke stejnému výsledku. V prvním případě nejsou explicitně inicializovány žádné proměnné. V druhém případě je vytvořena řetězcová proměnná a regulární výraz (jako literál). Ve třetím případě je regulární výraz vytvářen pomocí konstruktoru objektu RegExp.

Zapisujeme ve tvaru řetězec.replace(regexp, náhrada), kde řetězec je text, v němž má být provedeno nahrazení, regexp je regulární výraz popisující část řetězce, která má být nahrazena a náhrada je řetězec, kterým se má odpovídající část řetězce nahradit.

Funkce vrací upravený řetězec. Pokud chceme provést náhradu pro všechny (regulárnímu výrazu) odpovídající podřetězce, musíme použit modifikátor g. Jako součást náhrady můžeme také použít:

  • zpětnou referenci na část řetězce odpovídající regulárnímu výrazu (či subvýrazu)
  • část řetězce předcházející řetězci, který vytváří shodu
  • část řetězce následující po řetězci, který vytváří shodu

Způsoby, jak zapsat tyto speciální případy uvádí následující tabulka:

$1, ..., $99text, který odpovídá 1. až 99. regulárnímu subvýrazu
$&text, který odpovídá celému regulárnímu výrazu
$`text předcházející textu, který vytváří shodu s regulárním výrazem
$'text následující za textem, který vytváří shodu s regulárním výrazem

Mimochodem, pokud budete chtít v náhradě zapsat obyčejný znak dolaru v takovém místě, kde by ho bylo možno vykládat jako součást některé z výše uvedených speciálních konstrukcí, zapište dolar zdvojeně ($$). Například zápis $$1 tak nebude chápán jako reference na první subvýraz, ale jako prostý text "$1".

//replace() - příklad 1

//jediná náhrada - bez modifikátoru "g"
var str="15 USD, 10 EUR, 300 CZK";
var re1=/(\d+)\s(\w+)/;
var result1=str.replace(re1,"$2=$1"); //vrátí: USD=15, 10 EUR, 300 CZK
alert("Původní text: "+str+"\nZměněný text: "+result1);

//vícenásobná náhrada - s modifikátorem "g"
var str="15 USD, 10 EUR, 300 CZK";
var re2=/(\d+)\s(\w+)/g;
var result2=str.replace(re2,"$2=$1");
//vrátí: USD=15, EUR=10, CZK=300
alert("Původní text: "+str+"\nZměněný text: "+result2);

Myslím, že příklad ani nepotřebuje komentář. Je zřejmé, že bez použití modifikátoru g se řetězec následující po první úspěšné shodě (, 10 EUR, 300 CZK) ignoruje a k žádné záměně zde tak již nedochází.

Protože však regulární výraz /(\d+)\s(\w+)/ (nebo jeho verzi s modifikátorem g) budeme používat i v dalších příkladech (a jeho plné pochopení je tedy klíčové), připomenu raději jeho princip. Části (\d+) odpovídá sekvence číslic 0-9 (minimálně jedna číslice). Uzavření \d+ do kulatých závorek značí, že řetězec odpovídající regulárnímu subvýrazu \d+ je zapamatován a může být použit pomocí zpětné reference. Části \s odpovídá jeden "bílý znak" (například mezera či tabulátor - úplný výčet viz Regulární výrazy a JavaScript - úvod). Části (\w+) odpovídá sekvence alfanumerických znaků (včetně znaku podtržítka), přičemž je vyžadován minimálně jeden takový znak. Uzavření \w+ do kulatých závorek značí, že řetězec odpovídající regulárnímu subvýrazu \w+ (v našem případě označení příslušné měny) je zapamatován a může být použit pomocí zpětné reference.

Příklad 2:

//replace() - příklad 2

//náhrada obsahující celý řetězec odpovídající reg. výrazu
var str="15 USD, 10 EUR, 300 CZK";
var re3=/(\d+)\s(\w+)/g;
var result3=str.replace(re3,"Cena: $&");
//vrátí: Cena: 15 USD, Cena: 10 EUR, Cena: 300 CZK
alert("Původní text: "+str+"\nZměněný text: "+result3);

Jako náhrada je použit text Cena: následovaný referencí na text odpovídající celému regulárnímu výrazu ($&). Díky modifikátoru g se provede záměna třikrát.

//replace() - příklad 3

var str="abc12345def";
var re4=/\d+/;
var result4=str.replace(re4,"Před: $` - Za: $' - Shoda: $&");
//vrátí: abcPřed: abc - Za: def - Shoda: 12345def
alert("Původní text: "+str+"\nZměněný text: "+result4);

Tento příklad demonstruje použití speciálních konstrukcí z výše uvedené tabulky. Regulárnímu výrazu /\d+/ odpovídá v našem příkladu řetězec 12345. Pouze tento řetězec bude nahrazen "náhradou". Zbytek řetězce, který neodpovídá regulárnímu výrazu, bude vrácen bez změny (v našem případě sekvence znaků abc a sekvence znaků def).

//replace() - příklad 4

//uživatelská funkce
function desetkrat(cena)
{
return 10*cena;
};
var str="15 USD, 10 EUR, 300 CZK";
var re5=/\d+/g;
var result5=str.replace(re5,desetkrat);
//vrátí: 150 USD, 100 EUR, 3000 CZK
alert("Původní text: "+str+"\nZměněný text: "+result5);

Argumentem náhrada nemusí být jen řetězec, ale také název uživatelské funkce, která převezme jako svůj argument řetězec odpovídající regulárnímu výrazu, ten nějakým způsobem zpracuje a výsledek vrátí zpět metodě replace() (v PHP lze analogické chování docílit pomocí funkce preg_replace callback()). Volání uživatelské funkce se tedy provede pro každé jednotlivé nahrazení.

Jak vidíme, uživatelská funkce desetkrat() provádí prostý úkon - vynásobí funkci předanou hodnotu deseti (regulárnímu výrazu /\d+/g odpovídají pouze čísla obsažená v řetězci str). Jako náhrada je sice zadán název funkce desetkrat, avšak jako skutečná náhrada bude použita návratová hodnota této funkce.

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.