Tato aplikace bude (skoro) všechny tyto metody (nevyužijeme pouze
nejjednodušší dvě metody search()
a test()
)
používat při práci s řetězci a regulárními výrazy…
Co bude naše aplikace umět?
- najít části vstupního řetězce, které odpovídají regulárnímu
výrazu a vypsat je jako seznam oddělený libovolným oddělovačem (použijeme
match()
) - najít části vstupního řetězce, které odpovídají regulárnímu
výrazu, zaměnit je za náhradu (s možností použití zpětné
reference) a vrátit řetězec po provedení všech náhrad (použijeme
replace()
) - rozdělit vstupní řetězce s použitím oddělovače popsaného
pomocí regulárního výrazu a takto získané části spojit pomocí
libovolného oddělovače do výstupního řetězce (použijeme
split()
) - najít části vstupního řetězce, které odpovídají regulárnímu
výrazu (a jeho subvýrazům), a vypsat je jako číslovaný seznam shod
(formát připomínající dvourozměrné pole) (použijeme
exec()
)
Vyzkoušejte si nejdříve hotovou
aplikaci (zdrojový
kód). Jak vidíte, aplikace obsahuje šest textových vstupních polí
(regvyraz
, modifikatory
, oddelovac
,
nahrada
, vstup
, vystup
). Ne všechna pole
musí být vždy vyplněna – vždy záleží jakou akci (Match, Replace,
Split, Exec) budeme chtít provádět. Podívejme se na jednotlivá pole:
- Pole
vstup
obsahuje vstupní text (text, který chceme
zpracovat). - Pole
vystup
obsahuje text, který příslušná funkce
vrátí. - Pole
regvyraz
obsahuje regulární výraz zapsaný bez
oddělovačů (/
) a modifikátorů. - Pole
modifikatory
obsahuje řetězec složený z písmen
patřičných modifikátorů (napříkladg
,gi
a
podobně). - Pole
oddelovac
je použito pouze při akci Match nebo Split a
obsahuje oddělovač (respektive spojovací řetězec) jednotlivých
částí. - Pole
nahrada
je použito jen při akci Replace a obsahuje
řetězec, který se použije jako náhrada řetězce odpovídajícího
regulárnímu výrazu.
Analýza aplikace
Celá aplikace pracuje na velmi jednoduchém principu. Každé
z tlačítek (akcí) spustí jednu ze čtyř uživatelsky definovaných
funkcí (f_match()
, f_replace()
,
f_split()
, f_exec()
). Každá funkce načte
z polí formuláře vstupy, které použije jako argument příslušné
funkce (metody) postavené na regulárních výrazech (match()
,
replace()
, split()
, exec()
).
U metod, které vrací pole (match()
, split()
,
exec()
), je návratová hodnota převedena na řetězec pomocí
funkce join()
(u akcí Match a Split) nebo pomocí
procházení pole v cyklu a „ručního“ zřetězení prvků
pole (u akce Exec).
Zdrojový kód stránky s formulářem bude vypadat následovně:
<head>
<meta http-equiv=„Content-Type“ content=„text/html;
charset=windows-1250“/>
<meta http-equiv=„Content-language“
content=„cs“/>
<link rel=„stylesheet“ type=„text/css“
href=„reapp.css“/>
<title>Javascript RegExp All-in-1 Tool</title>
<script type=„text/javascript“>
…
zde budou jednotlivé funkce (zdrojový kód viz níže)
…
</script>
</head>
<body>
<h1>Javascript RegExp All-in-1 Tool</h1>
<form id=„reapp“ name=„reapp“ action=““
onsubmit=„return false;“>
<table>
<tr>
<td class=„popis“>Regulární
výraz</td>
<td><input class=„txtinput“
type=„text“ name=„regvyraz“ /></td>
</tr>
<tr>
<td
class=„popis“>Modifikátory</td>
<td><input class=„txtinput“
type=„text“ name=„modifikatory“ /></td>
</tr>
<tr>
<td
class=„popis“>Oddělovač</td>
<td><input class=„txtinput“
type=„text“ name=„oddelovac“ /></td>
</tr>
<tr>
<td
class=„popis“>Náhrada</td>
<td><input class=„txtinput“
type=„text“ name=„nahrada“ /></td>
</tr>
<tr>
<td
class=„popis“>Vstup</td>
<td><textarea name=„vstup“
cols=„60“ rows=„20“>
</textarea></td>
</tr>
<tr>
<td
class=„popis“>Výstup</td>
<td><textarea name=„vystup“
cols=„60“ rows=„20“>
</textarea></td>
</tr>
<tr>
<td
class=„popis“>Akce</td>
<td>
<input value=„Match“
type=„submit“ onclick=„f_match()“ />
<input value=„Replace“
type=„submit“ onclick=„f_replace()“ />
<input value=„Split“
type=„submit“ onclick=„f_split()“ />
<input value=„Exec“
type=„submit“ onclick=„f_exec()“ />
</td>
</tr>
</table>
</form>
</body>
</html>
Ve výše uvedeném kódu jsou u některých elementů uvedeny CSS
třídy odpovídající externí definici stylů, stylování stránky se však
v tomto článku věnovat nebudeme. Výše uvedený zdrojový kód stránky
neobsahuje vlastní javascriptové funkce – na ty se podíváme
samostatně níže. V kódu stojí za pozornost ještě zápis
<form id=„reapp“ name=„reapp“ action="" onsubmit=„return false;“>
,
respektive především akce
onsubmit=„return false;“
, která zajistí,
že kliknutí na tlačítka Match, Replace, Split či Exec (což jsou
input
prvky typu submit
) nezpůsobí odeslání
formuláře.
Funkce f_match()
{
var vstup1=document.reapp.vstup.value;
var regvyraz1=new
RegExp(document.reapp.regvyraz.value,document.reapp.modifikatory.value);
var result=vstup1.match(regvyraz1);
document.reapp.vystup.value=result.join(document.reapp.oddelovac.value);
};
Funkce f_match()
je jednoduchá a snad by ani žádný
komentář nevyžadovala. Přesto, pár slov se na tomto místě sluší.
Vstupní text (řetězec, načtený z formuláře) si uložíme do
proměnné vstup1
, poté vytvoříme instanci objektu
RegExp
– regvyraz1
. Takto vzniklé proměnné
použijeme pro metodu match()
. Pole result
, které
metoda match()
vrátí, převedeme pomocí metody
join()
na řetězec, který zobrazíme v prvku
textarea
.
Funkce f_replace()
{
var vstup1=document.reapp.vstup.value;
var regvyraz1=new
RegExp(document.reapp.regvyraz.value,document.reapp.modifikatory.value);
var
result=vstup1.replace(regvyraz1,document.reapp.nahrada.value);
document.reapp.vystup.value=result;
};
Funkce f_replace()
je velmi podobná. Dokonce je ještě
jednodušší, protože metoda replace()
vrátí přímo řetězec,
který se zobrazí v textarea
.
Funkce f_split()
{
var vstup1=document.reapp.vstup.value;
var regvyraz1=new
RegExp(document.reapp.regvyraz.value,document.reapp.modifikatory.value);
var result=vstup1.split(regvyraz1);
document.reapp.vystup.value=result.join(document.reapp.oddelovac.value);
};
Funkce f_split()
má analogickou strukturu jako
f_replace()
. Jediný (ale podstatný) rozdíl je v tom, že
regulární výraz popisuje řetězec, pomocí nějž se má vstupní text
(řetězec) rozdělit na části. Takto vzniklé části (pole řetězců) se
opět převedou s použitím metody join()
na výstupní
řetězec.
Funkce f_exec()
{
var vstup1=document.reapp.vstup.value;
var regvyraz1=new
RegExp(document.reapp.regvyraz.value,document.reapp.modifikatory.value);
var i=0; //inicializace – počet nalezených shod
var subvyrazy=““; //řetězec pro zapamatování
výstupu
while(result1=regvyraz1.exec(vstup1))
{
for(var j=0;result1[j];j++)
subvyrazy=subvyrazy+„[“+i+„][“+j+„]:
„+result1[j]+“\n“;
if(!regvyraz1.global) break;
//opatření proti zacyklení
i++; //inkrementace – počet
nalezených shod
};
document.reapp.vystup.value=subvyrazy;
};
Kód funkce f_exec()
je velmi podobný kódu příkladu
(u metody exec()
) v předcházejícím článku. Tato
funkce je přeci jen o něco složitější než tři předcházející,
proto doporučuji si nejdříve vyzkoušet při jakých vstupech (regulární
výraz, modifikátory, vstupní text) vrací jaký výstup (respektive
především jak je výstup formátován).
Funkce je postavena na dvou vnořených cyklech. Vnější while
cyklus slouží k opakovanému volání metody exec()
při
globálním prohledávání (počet průchodů cyklem zaznamenává počítadlo
i
). Vnořený cyklus for
slouží k procházení
shod s jednotlivými subvýrazy, tedy de facto pro procházení pole,
které vrátí metoda exec()
(počet průchodů tímto cyklem
zaznamenává počítadlo j
). V cyklu while
voláme opakovaně result1=regvyraz1.exec(vstup1)
.
Navrácené pole result1
procházíme ve for
cyklu a
do řetězcové proměnné subvyrazy
vždy zapíšeme (respektive
připíšeme) shodu ve tvaru
[i][j]: shoda
, kde
i udává o kolikátou shodu (při globálním
vyhledávání) se jedná (indexováno od nuly!) a j udává,
o shodu s kolikátým subvýrazem se jedná (shoda s celým
regulárním výrazem je pod indexem 0
).
Určitá komplikace nastává v případě, že nepoužijeme
modifikátor g
(globální vyhledávání). V takovém
případě 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. V našem
jednoduchém kódu si dovolím pro řešení použít programátorsky ne zcela
nejčistší řešení, a to opuštění while
cyklu pomocí
break
na základě otestování vlastnosti global
regulárního výrazu. Zápis
if(!regvyraz1.global) break;
tedy říká: Pokud
regulární výraz neobsahuje modifikátor pro globální vyhledávání, opusť
cyklus.
Souhrn
Nastíněné řešení je pouze jádrem uživatelsky komfortní aplikace.
Není však již velkým problémem například místo textového vstupního
pole pro regulární výraz použít rozbalovací menu s přednastavenými
regulárními výrazy a podobně, a tak zpřístupnit funkčnost
i uživatelům, kteří se tolik s regulárními výrazy
nekamarádí.
Interval.cz, kde naleznete originální verzi článku.
Nenech si to pro sebe...
Pokud tě článek zaujal, sdílej ho s ostatními. Díky!