V tomto článku se budeme zabývat různými metodami, které pracují s regulárními výrazy do hloubky.
str.match(regexp)
Metoda str.match(regexp)
najde shody pro regexp
v řetězci str
.
Má 3 režimy:
-
Pokud
regexp
nemá příznakg
, pak vrátí první shodu jako pole se zachycujícími skupinami a vlastnostmiindex
(pozice shody),input
(vstupní řetězec se rovnástr
):let str = "I love JavaScript"; let result = str.match(/Java(Script)/); alert( result[0] ); // JavaScript (full match) alert( result[1] ); // Script (first capturing group) alert( result.length ); // 2 // Additional information: alert( result.index ); // 7 (match position) alert( result.input ); // I love JavaScript (source string)
-
Pokud
regexp
má příznakg
, pak vrátí pole všech shod jako řetězce, bez zachycení skupin a dalších podrobností.let str = "I love JavaScript"; let result = str.match(/Java(Script)/g); alert( result[0] ); // JavaScript alert( result.length ); // 1
-
Pokud neexistují žádné shody, bez ohledu na to, zda je příznak
g
nebo ne,null
je vráceno.To je důležitá nuance. Pokud neexistují žádné shody, nezískáme prázdné pole, ale
null
. Je snadné udělat chybu a zapomenout na to, např.:let str = "I love JavaScript"; let result = str.match(/HTML/); alert(result); // null alert(result.length); // Error: Cannot read property 'length' of null
Pokud chceme, aby výsledkem bylo pole, můžeme napsat takto:
let result = str.match(regexp) || [];
str.matchAll(regexp)
Nedávný přírůstek Toto je nedávný přírůstek do jazyka. Staré prohlížeče mohou vyžadovat polyfilly.
Metoda str.matchAll(regexp)
je „novější, vylepšená“ varianta str.match
.
Používá se hlavně k vyhledávání všech zápasů se všemi skupinami.
Existují 3 rozdíly oproti match
:
- Namísto pole vrací iterovatelný objekt se shodami. Můžeme z něj vytvořit běžné pole pomocí
Array.from
. - Každá shoda je vrácena jako pole se zachycujícími skupinami (stejný formát jako
str.match
bez příznakug
). - Pokud nejsou k dispozici žádné výsledky, vrátí prázdný iterovatelný objekt namísto
null
.
Příklad použití:
let str = '<h1>Hello, world!</h1>';
let regexp = /<(.*?)>/g;
let matchAll = str.matchAll(regexp);
alert(matchAll); // [object RegExp String Iterator], not array, but an iterable
matchAll = Array.from(matchAll); // array now
let firstMatch = matchAll[0];
alert( firstMatch[0] ); // <h1>
alert( firstMatch[1] ); // h1
alert( firstMatch.index ); // 0
alert( firstMatch.input ); // <h1>Hello, world!</h1>
Pokud použijeme for..of
smyčka přes matchAll
shod, pak nepotřebujeme Array.from
nic víc.
str.split(regexp|substr, limit)
Rozdělí řetězec pomocí regulárního výrazu (nebo podřetězce) jako oddělovače.
Můžeme použít split
s řetězci, jako je tento:
alert('12-34-56'.split('-')) // array of ['12', '34', '56']
Ale můžeme rozdělit regulárním výrazem stejným způsobem:
alert('12, 34, 56'.split(/,\s*/)) // array of ['12', '34', '56']
str.search(regexp)
Metoda str.search(regexp)
vrátí pozici první shody nebo -1
pokud žádný nebyl nalezen:
let str = "A drop of ink may make a million think";
alert( str.search( /ink/i ) ); // 10 (first match position)
Důležité omezení:search
najde pouze první shodu.
Pokud potřebujeme pozice dalších shod, měli bychom použít jiné prostředky, jako je najít všechny pomocí str.matchAll(regexp)
.
str.replace(str|regexp, str|func)
Toto je obecná metoda pro vyhledávání a nahrazování, jedna z nejužitečnějších. Švýcarský armádní nůž pro hledání a výměnu.
Můžeme jej použít bez regulárních výrazů k vyhledání a nahrazení podřetězce:
// replace a dash by a colon
alert('12-34-56'.replace("-", ":")) // 12:34-56
Je tu však úskalí.
Při prvním argumentu replace
je řetězec, pouze nahrazuje první shodu.
Můžete to vidět v příkladu výše:pouze první "-"
je nahrazeno ":"
.
Abychom našli všechny spojovníky, musíme použít nikoli řetězec "-"
, ale regulární výraz /-/g
s povinným g
příznak:
// replace all dashes by a colon
alert( '12-34-56'.replace( /-/g, ":" ) ) // 12:34:56
Druhý argument je náhradní řetězec. Můžeme v něm použít speciální znaky:
Symboly | Akce v náhradním řetězci |
---|---|
$& | vloží celou shodu |
$` | vloží část řetězce před shodu |
$' | vloží část řetězce za shodu |
$n | if n je 1-2 místné číslo, vkládá obsah n-té skupiny zachycení, podrobnosti viz Zachytávání skupin |
$<name> | vloží obsah závorek s daným name , podrobnosti viz Zachycování skupin |
$$ | vloží znak $ |
Například:
let str = "John Smith";
// swap first and last name
alert(str.replace(/(john) (smith)/i, '$2, $1')) // Smith, John
V situacích, které vyžadují „chytré“ nahrazení, může být druhým argumentem funkce.
Bude volána pro každou shodu a vrácená hodnota bude vložena jako náhrada.
Funkce se volá s argumenty func(match, p1, p2, ..., pn, offset, input, groups)
:
match
– zápas,p1, p2, ..., pn
– obsah zachytávacích skupin (pokud nějaké existují),offset
– postavení zápasu,input
– zdrojový řetězec,groups
– objekt s pojmenovanými skupinami.
Pokud v regulárním výrazu nejsou žádné závorky, pak existují pouze 3 argumenty:func(str, offset, input)
.
Uveďme například všechny shody velkými písmeny:
let str = "html and css";
let result = str.replace(/html|css/gi, str => str.toUpperCase());
alert(result); // HTML and CSS
Nahraďte každou shodu její pozicí v řetězci:
alert("Ho-Ho-ho".replace(/ho/gi, (match, offset) => offset)); // 0-3-6
V příkladu níže jsou dvě závorky, takže funkce nahrazení je volána s 5 argumenty:první je úplná shoda, pak 2 závorky a za ní (v příkladu se nepoužívá) pozice shody a zdrojový řetězec:
let str = "John Smith";
let result = str.replace(/(\w+) (\w+)/, (match, name, surname) => `${surname}, ${name}`);
alert(result); // Smith, John
Pokud je skupin mnoho, je vhodné pro přístup k nim použít parametry odpočinku:
let str = "John Smith";
let result = str.replace(/(\w+) (\w+)/, (...match) => `${match[2]}, ${match[1]}`);
alert(result); // Smith, John
Nebo, pokud používáme pojmenované skupiny, pak groups
objekt s nimi je vždy poslední, takže jej můžeme získat takto:
let str = "John Smith";
let result = str.replace(/(?<name>\w+) (?<surname>\w+)/, (...match) => {
let groups = match.pop();
return `${groups.surname}, ${groups.name}`;
});
alert(result); // Smith, John
Použití funkce nám poskytuje maximální nahrazovací sílu, protože získává všechny informace o shodě, má přístup k vnějším proměnným a může dělat všechno.
str.replaceAll(str|regexp, str|func)
Tato metoda je v podstatě stejná jako str.replace
, se dvěma hlavními rozdíly:
- Pokud je prvním argumentem řetězec, nahradí všechny výskyty řetězce, zatímco
replace
nahradí pouze první výskyt . - Pokud je prvním argumentem regulární výraz bez
g
příznak, dojde k chybě. Sg
flag, funguje stejně jakoreplace
.
Hlavní případ použití pro replaceAll
nahrazuje všechny výskyty řetězce.
Takhle:
// replace all dashes by a colon
alert('12-34-56'.replaceAll("-", ":")) // 12:34:56
regexp.exec(str)
regexp.exec(str)
metoda vrací shodu pro regexp
v řetězci str
. Na rozdíl od předchozích metod se volá na regulárním výrazu, nikoli na řetězci.
Chová se odlišně v závislosti na tom, zda má regulární výraz příznak g
.
Pokud neexistuje g
a poté regexp.exec(str)
vrátí první shodu přesně jako str.match(regexp)
. Toto chování nepřináší nic nového.
Ale pokud je tam příznak g
, pak:
- Volání na číslo
regexp.exec(str)
vrátí první shodu a uloží pozici bezprostředně za ní do vlastnostiregexp.lastIndex
. - Další takové volání zahájí vyhledávání od pozice
regexp.lastIndex
, vrátí další shodu a uloží pozici za ní doregexp.lastIndex
. - …A tak dále.
- Pokud neexistují žádné shody,
regexp.exec
vrátínull
a resetujeregexp.lastIndex
na0
.
Opakovaná volání tedy vracejí všechny shody jednu po druhé pomocí vlastnosti regexp.lastIndex
pro sledování aktuální pozice vyhledávání.
V minulosti před metodou str.matchAll
byl přidán do JavaScriptu, volání regexp.exec
byly použity ve smyčce k získání všech zápasů se skupinami:
let str = 'More about JavaScript at https://javascript.info';
let regexp = /javascript/ig;
let result;
while (result = regexp.exec(str)) {
alert( `Found ${result[0]} at position ${result.index}` );
// Found JavaScript at position 11, then
// Found javascript at position 33
}
To nyní funguje také, i když pro novější prohlížeče str.matchAll
je obvykle pohodlnější.
Můžeme použít regexp.exec
pro vyhledávání z dané pozice ručním nastavením lastIndex
.
Například:
let str = 'Hello, world!';
let regexp = /\w+/g; // without flag "g", lastIndex property is ignored
regexp.lastIndex = 5; // search from 5th position (from the comma)
alert( regexp.exec(str) ); // world
Pokud má regulární výraz příznak y
, pak bude vyhledávání provedeno přesně na pozici regexp.lastIndex
, dále ne.
Nahradíme příznak g
s y
ve výše uvedeném příkladu. Nebudou nalezeny žádné shody, protože na pozici 5
není žádné slovo :
let str = 'Hello, world!';
let regexp = /\w+/y;
regexp.lastIndex = 5; // search exactly at position 5
alert( regexp.exec(str) ); // null
To se hodí v situacích, kdy potřebujeme něco „přečíst“ z řetězce podle regulárního výrazu na přesné pozici, nikoli někde dále.
regexp.test(str)
Metoda regexp.test(str)
vyhledá shodu a vrátí true/false
zda existuje.
Například:
let str = "I love JavaScript";
// these two tests do the same
alert( /love/i.test(str) ); // true
alert( str.search(/love/i) != -1 ); // true
Příklad se zápornou odpovědí:
let str = "Bla-bla-bla";
alert( /love/i.test(str) ); // false
alert( str.search(/love/i) != -1 ); // false
Pokud má regulární výraz příznak g
a poté regexp.test
vypadá z regexp.lastIndex
vlastnost a aktualizuje tuto vlastnost, stejně jako regexp.exec
.
Můžeme jej tedy použít k vyhledávání z dané pozice:
let regexp = /love/gi;
let str = "I love JavaScript";
// start the search from position 10:
regexp.lastIndex = 10;
alert( regexp.test(str) ); // false (no match)
Stejný globální regulární výraz testovaný opakovaně na různých zdrojích může selhat
Pokud použijeme stejný globální regulární výraz na různé vstupy, může to vést k nesprávnému výsledku, protože regexp.test
zálohy volání regexp.lastIndex
vlastnost, takže hledání v jiném řetězci může začít od nenulové pozice.
Například zde nazýváme regexp.test
dvakrát na stejném textu a podruhé se nezdaří:
let regexp = /javascript/g; // (regexp just created: regexp.lastIndex=0)
alert( regexp.test("javascript") ); // true (regexp.lastIndex=10 now)
alert( regexp.test("javascript") ); // false
To je přesně proto, že regexp.lastIndex
je ve druhém testu nenulový.
Abychom to vyřešili, můžeme nastavit regexp.lastIndex = 0
před každým hledáním. Nebo místo volání metod na regulárním výrazu použijte řetězcové metody str.match/search/...
, nepoužívají lastIndex
.