V tomto Älánku probereme do hloubky různé metody, které pracujà s regulárnÃmi výrazy.
ÅetÄzec.match(rv)
Metoda ÅetÄzec.match(rv) najde shody regulárnÃho výrazu rv v ÅetÄzci ÅetÄzec.
Pracuje ve tÅech režimech:
-
Jestliže
rvneobsahuje pÅÃznakg, pak metoda vrátà prvnà shodu jako pole se zachytávacÃmi skupinami a vlastnostmiindex(pozice shody),input(vstupnà ÅetÄzec, je rovenÅetÄzec):let ÅetÄzec = "Mám rád JavaScript"; let výsledek = ÅetÄzec.match(/Java(Script)/); alert( výsledek[0] ); // JavaScript (celá shoda) alert( výsledek[1] ); // Script (prvnà zachytávacà skupina) alert( výsledek.length ); // 2 // Dalšà informace: alert( výsledek.index ); // 8 (pozice shody) alert( výsledek.input ); // Mám rád JavaScript (zdrojový ÅetÄzec) -
Jestliže
rvobsahuje pÅÃznakg, pak metoda vrátà pole vÅ¡ech shod jako ÅetÄzce, bez zachytávacÃch skupin a dalÅ¡Ãch detailů.let ÅetÄzec = "Mám rád JavaScript"; let výsledek = ÅetÄzec.match(/Java(Script)/g); alert( výsledek[0] ); // JavaScript alert( výsledek.length ); // 1 -
Jestliže žádné shody nejsou, metoda bez ohledu na pÅÃtomnost pÅÃznaku
gvrátÃnull.To je důležitý detail. Pokud nenastanou žádné shody, neobdržÃme prázdné pole, ale
null. Je snadné na to zapomenout a udÄlat chybu, napÅÃklad:let ÅetÄzec = "Mám rád JavaScript"; let výsledek = ÅetÄzec.match(/HTML/); alert(výsledek); // null alert(výsledek.length); // Error: Cannot read property 'length' of nullPokud chceme, aby výsledek byl pole, můžeme to zapsat následovnÄ:
let výsledek = ÅetÄzec.match(rv) || [];
ÅetÄzec.matchAll(rv)
Metoda ÅetÄzec.matchAll(rv) je ânovÄjšà a vylepÅ¡enáâ varianta metody ÅetÄzec.match.
PoužÃvá se pÅevážnÄ k hledánà vÅ¡ech shod se vÅ¡emi skupinami.
Od metody match se lišà ve tÅech vÄcech:
- NamÃsto pole vracà iterovatelný objekt se shodami. Můžeme z nÄj vytvoÅit skuteÄné pole pomocÃ
Array.from. - Každá shoda se vrátà jako pole se zachytávacÃmi skupinami (ve stejném formátu jako u
ÅetÄzec.matchbez pÅÃznakug). - Pokud žádné výsledky nejsou, mÃsto
nullvrátà prázdný iterovatelný objekt.
PÅÃklad použitÃ:
let ÅetÄzec = '<h1>Ahoj, svÄte!</h1>';
let rv = /<(.*?)>/g;
let matchAll = ÅetÄzec.matchAll(rv);
alert(matchAll); // [object RegExp String Iterator], ne pole, ale iterovatelný objekt
matchAll = Array.from(matchAll); // teÄ je to pole
let prvnÃShoda = matchAll[0];
alert( prvnÃShoda[0] ); // <h1>
alert( prvnÃShoda[1] ); // h1
alert( prvnÃShoda.index ); // 0
alert( prvnÃShoda.input ); // <h1>Ahoj, svÄte!</h1>
Pokud budeme procházet shody z metody matchAll pomocà cyklu for..of, nebudeme už Array.from potÅebovat.
ÅetÄzec.split(rv|podÅetÄzec, limit)
RozdÄlà ÅetÄzec podle regulárnÃho výrazu (nebo podÅetÄzce) jako oddÄlovaÄe.
Můžeme použÃt split s ÅetÄzci, napÅÃklad:
alert('12-34-56'.split('-')) // pole ['12', '34', '56']
Stejným způsobem vÅ¡ak můžeme rozdÄlovat i podle regulárnÃho výrazu:
alert('12, 34, 56'.split(/,\s*/)) // pole ['12', '34', '56']
ÅetÄzec.search(rv)
Metoda ÅetÄzec.search(rv) vrátà pozici prvnà shody nebo -1, pokud shoda nebyla nalezena:
let ÅetÄzec = "A drop of ink may make a million think";
alert( ÅetÄzec.search( /ink/i ) ); // 10 (pozice prvnà shody)
Důležité omezenÃ: search najde pouze prvnà shodu.
Jestliže potÅebujeme i pozice dalÅ¡Ãch shod, mÄli bychom je najÃt jiným způsobem, napÅÃklad pomocà ÅetÄzec.matchAll(rv).
ÅetÄzec.replace(ÅetÄzec|rv, ÅetÄzec|funkce)
Toto je obecná metoda pro hledánà a nahrazovánÃ, jedna z nejužiteÄnÄjÅ¡Ãch. Å výcarský armádnà nůž pro hledánà a nahrazovánÃ.
Můžeme ji použÃt bez regulárnÃch výrazů k nalezenà a nahrazenà podÅetÄzce:
// nahradà pomlÄku dvojteÄkou
alert('12-34-56'.replace("-", ":")) // 12:34-56
Je tady však jedna záludnost.
Pokud je prvnÃm argumentem replace ÅetÄzec, metoda nahradà jen prvnà shodu.
Můžete to vidÄt v uvedeném pÅÃkladu: za ":" byla nahrazena jedinÄ prvnà "-".
Abychom naÅ¡li vÅ¡echny pomlÄky, nesmÃme použÃt ÅetÄzec "-", ale regulárnà výraz /-/g s povinným pÅÃznakem g:
// nahradà vÅ¡echny pomlÄky dvojteÄkou
alert( '12-34-56'.replace( /-/g, ":" ) ) // 12:34:56
Druhým argumentem je nahrazovacà ÅetÄzec. Můžeme v nÄm použÃvat speciálnà znaky:
| Symboly | Akce v nahrazovacÃm ÅetÄzci |
|---|---|
$& |
vložà celou shodu |
$` |
vložà Äást ÅetÄzce pÅed shodou |
$' |
vložà Äást ÅetÄzce za shodou |
$n |
pokud n je 1-2ciferné ÄÃslo, vložà obsah n-té zachytávacà skupiny, podrobnosti viz Zachytávacà skupiny |
$<jméno> |
vložà obsah závorek se jménem jméno, podrobnosti viz Zachytávacà skupiny |
$$ |
vložà znak $ |
PÅÃklad:
let ÅetÄzec = "Jan Novák";
// pÅehodà jméno a pÅÃjmenÃ
alert(ÅetÄzec.replace(/(jan) (novák)/i, '$2, $1')) // Novák, Jan
V situacÃch, které vyžadujà âchytréâ nahrazenÃ, může být druhým argumentem funkce.
Tato funkce bude volána pro každou shodu a jako nahrazovacà ÅetÄzec pak bude vložena jejà návratová hodnota.
Funkce bude volána s argumenty funkce(shoda, p1, p2, ..., pn, pozice, vstup, skupiny):
shodaâ shoda,p1, p2, ..., pnâ obsahy zachytávacÃch skupin (pokud nÄjaké jsou),poziceâ pozice shody,vstupâ zdrojový ÅetÄzec,skupinyâ objekt s pojmenovanými skupinami.
Pokud regulárnà výraz neobsahuje závorky, pak jsou argumenty pouze tÅi: funkce(ÅetÄzec, pozice, vstup).
NapÅÃklad pÅeveÄme vÅ¡echny shody na velká pÃsmena:
let ÅetÄzec = "html a css";
let výsledek = ÅetÄzec.replace(/html|css/gi, ÅetÄzec => ÅetÄzec.toUpperCase());
alert(výsledek); // HTML a CSS
Každou shodu nahraÄme jejà pozicà v ÅetÄzci:
alert("Ha-Ha-ha".replace(/ha/gi, (shoda, pozice) => pozice)); // 0-3-6
V následujÃcÃm pÅÃkladu jsou dvoje závorky, takže nahrazovacà funkce je volána s 5 argumenty: prvnà je celá shoda, pak jsou 2 závorky a po nich (v pÅÃkladu nepoužité) pozice shody a zdrojový ÅetÄzec:
let ÅetÄzec = "Jan Novak";
let výsledek = ÅetÄzec.replace(/(\w+) (\w+)/, (shoda, jméno, pÅÃjmenÃ) => `${pÅÃjmenÃ}, ${jméno}`);
alert(výsledek); // Novak, Jan
Pokud je skupin mnoho, je vhodné pÅistupovat k nim pomocà zbytkových parametrů:
let ÅetÄzec = "Jan Novak";
let výsledek = ÅetÄzec.replace(/(\w+) (\w+)/, (...shoda) => `${shoda[2]}, ${shoda[1]}`);
alert(výsledek); // Novak, Jan
Nebo jestliže použÃváme pojmenované skupiny, objekt skupiny s nimi je vždy poslednÃ, takže jej můžeme zÃskat následovnÄ:
let ÅetÄzec = "Jan Novak";
let výsledek = ÅetÄzec.replace(/(?<jméno>\w+) (?<pÅÃjmenÃ>\w+)/, (...shoda) => {
let skupiny = shoda.pop();
return `${skupiny.pÅÃjmenÃ}, ${skupiny.jméno}`;
});
alert(výsledek); // Novak, Jan
Použità funkce nám dává mocnou nahrazovacà sÃlu, jelikož funkce obdržà vÅ¡echny informace o shodÄ, má pÅÃstup k vnÄjÅ¡Ãm promÄnným a může udÄlat cokoli.
ÅetÄzec.replaceAll(ÅetÄzec|rv, ÅetÄzec|funkce)
Tato metoda je v zásadÄ stejná jako ÅetÄzec.replace, ale má dva hlavnà rozdÃly:
- Pokud je prvnà argument ÅetÄzec, nahradà vÅ¡echny výskyty tohoto ÅetÄzce, zatÃmco
replacenahrazuje jedinÄ prvnà výskyt. - Pokud je prvnà argument regulárnà výraz bez pÅÃznaku
g, nastane chyba. S pÅÃznakemgfunguje stejnÄ jakoreplace.
Hlavnà využità metody replaceAll je nahrazenà vÅ¡ech výskytů ÅetÄzce.
NapÅÃklad:
// nahradà vÅ¡echny pomlÄky dvojteÄkou
alert('12-34-56'.replaceAll("-", ":")) // 12:34:56
rv.exec(ÅetÄzec)
Metoda rv.exec(ÅetÄzec) vrátà shodu s regulárnÃm výrazem rv v ÅetÄzci ÅetÄzec. Na rozdÃl od pÅedchozÃch metod se nevolá na ÅetÄzci, ale na regulárnÃm výrazu.
Chová se odliÅ¡nÄ podle toho, zda regulárnà výraz obsahuje pÅÃznak g.
Pokud neobsahuje g, pak rv.exec(ÅetÄzec) vrátà prvnà shodu stejnÄ, jako ÅetÄzec.match(rv). Toto chovánà nepÅinášà nic nového.
AvÅ¡ak pokud je pÅÃznak g uveden, pak:
- VolánÃ
rv.exec(ÅetÄzec)vrátà prvnà shodu a uložà pozici bezprostÅednÄ za nà do vlastnostirv.lastIndex. - Dalšà takové volánà zaÄne hledat od pozice
rv.lastIndex, vrátà dalšà shodu a uložà pozici bezprostÅednÄ za nà dorv.lastIndex. - â¦A tak dále.
- Pokud nejsou žádné shody,
rv.execvrátÃnulla vyresetujerv.lastIndexna0.
Opakovaná volánà tedy vracejà vÅ¡echny shody jednu po druhé a ve vlastnosti rv.lastIndex si pamatujà aktuálnà pozici hledánÃ.
V minulosti, než byla do JavaScriptu pÅidána metoda ÅetÄzec.matchAll, se volánà rv.exec použÃvala v cyklu k zÃskánà vÅ¡ech shod ve skupinách:
let ÅetÄzec = 'VÃce se o JavaScriptu dozvÃte na https://javascript.info';
let rv = /javascript/ig;
let výsledek;
while (výsledek = rv.exec(ÅetÄzec)) {
alert( `Nalezeno ${výsledek[0]} na pozici ${výsledek.index}` );
// Nalezeno JavaScript na pozici 10, pak
// Nalezeno javascript na pozici 40
}
To funguje dosud, aÄkoli u nových prohlÞeÄů je ÅetÄzec.matchAll zpravidla vhodnÄjÅ¡Ã.
Můžeme použÃt rv.exec pro hledánà od zadané pozice, když nastavÃme lastIndex ruÄnÄ.
NapÅÃklad:
let ÅetÄzec = 'Ahoj, svete!';
let rv = /\w+/g; // bez pÅÃznaku "g" je vlastnost lastIndex ignorována
rv.lastIndex = 5; // hledá od 5. pozice (od Äárky)
alert( rv.exec(ÅetÄzec) ); // svete
Pokud RV obsahuje pÅÃznak y, pak bude hledánà provedeno výhradnÄ na pozici rv.lastIndex a nikde dál.
NahraÄme v uvedeném pÅÃkladu pÅÃznak g pÅÃznakem y. Nenajde se žádná shoda, protože na pozici 5 nenà žádné slovo:
let ÅetÄzec = 'Ahoj, svete!';
let rv = /\w+/y;
rv.lastIndex = 5; // hledá výhradnÄ na pozici 5
alert( rv.exec(ÅetÄzec) ); // null
To se hodà v situacÃch, kdy potÅebujeme z ÅetÄzce nÄco ânaÄÃstâ regulárnÃm výrazem z pÅesnÄ dané pozice, ale ne odnikud dál.
rv.test(ÅetÄzec)
Metoda rv.test(ÅetÄzec) se pokusà najÃt shodu a vrátà true/false podle toho, zda existuje.
NapÅÃklad:
let ÅetÄzec = "Mám rád JavaScript";
// tyto dva testy udÄlajà totéž
alert( /rád/i.test(ÅetÄzec) ); // true
alert( ÅetÄzec.search(/rád/i) != -1 ); // true
PÅÃklad se zápornou odpovÄdÃ:
let ÅetÄzec = "Bla-bla-bla";
alert( /rád/i.test(ÅetÄzec) ); // false
alert( ÅetÄzec.search(/rád/i) != -1 ); // false
Jestliže RV obsahuje pÅÃznak g, pak rv.test hledá od vlastnosti rv.lastIndex a aktualizuje ji, stejnÄ jako rv.exec.
Můžeme ji tedy použÃt pro hledánà od urÄité pozice:
let rv = /rád/gi;
let ÅetÄzec = "Mám rád JavaScript";
// zaÄneme hledat na pozici 10:
rv.lastIndex = 10;
alert( rv.test(ÅetÄzec) ); // false (žádná shoda)
Jestliže aplikujeme stejný globálnà RV na různé vstupy, může vést k nesprávnému výsledku, protože volánà rv.test posune vlastnost rv.lastIndex, takže hledánà v jiném ÅetÄzci může zaÄÃt od nenulové pozice.
NapÅÃklad zde voláme rv.test dvakrát na stejném textu a druhé volánà selže:
let rv = /javascript/g; // (rv právÄ vytvoÅen: rv.lastIndex=0)
alert( rv.test("javascript") ); // true (teÄ je rv.lastIndex=10)
alert( rv.test("javascript") ); // false
Je to právÄ proto, že ve druhém testu je rv.lastIndex nenulová.
Abychom se tomu vyhnuli, můžeme pÅed každým hledánÃm nastavit rv.lastIndex = 0. Anebo mÃsto volánà metod na regulárnÃm výrazu použijeme ÅetÄzcové metody ÅetÄzec.match/search/..., které lastIndex nepoužÃvajÃ.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)