Více znaků nebo znakových tříd uvnitř hranatých závorek […] znamená „najdi kterýkoli z uvedených znaků“.
Množiny
Například [eao] znamená kterýkoli z těchto 3 znaků: 'a', 'e' nebo 'o'.
To se nazývá množina. Množiny lze používat v regulárním výrazu spolu s běžnými znaky:
// najdi [t nebo m] a pak "op"
alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top"
Prosíme všimněte si, že ačkoli je v množině několik znaků, ve shodě jim odpovídá právě jeden znak.
Následující příklad tedy nenajde žádnou shodu:
// najdi "V", pak [o nebo i], pak "la"
alert( "Voila".match(/V[oi]la/) ); // null, žádná shoda
Vzor hledá:
V,- pak jedno z písmen
[oi], - pak
la.
Shoda tedy nastane pro Vola nebo Vila.
Rozsahy
Hranaté závorky mohou obsahovat i rozsahy znaků.
Například [a-z] znamená libovolný znak v rozsahu od a do z a [0-5] znamená číslici od 0 do 5.
V následujícím příkladu hledáme "x", po němž následují dvě číslice nebo písmena od A do F:
alert( "Výjimka 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF
Zde [0-9A-F] obsahuje dva rozsahy: najde znak, kterým je buď číslice od 0 do 9, nebo písmeno od A do F.
Kdybychom chtěli hledat i malá písmena, mohli bychom přidat rozsah a-f: [0-9A-Fa-f]. Nebo uvést příznak i.
Uvnitř […] můžeme používat i znakové třídy.
Kdybychom například chtěli hledat slovní znak \w nebo pomlčku -, pak by množina byla [\w-].
Je možné i kombinovat více tříd, např. [\s\d] znamená „mezerový znak nebo číslice“.
Například:
- \d – je totéž jako
[0-9], - \w – je totéž jako
[a-zA-Z0-9_], - \s – je totéž jako
[\t\n\v\f\r ]plus několik dalších vzácných mezerových znaků z Unicode.
Příklad: vícejazyčné \w
Protože znaková třída \w je zkratkou pro [a-zA-Z0-9_], nedokáže najít čínské hieroglyfy, písmena kyrilice a podobně.
Můžeme si napsat univerzálnější vzor, který bude hledat slovní znaky jakéhokoli jazyka. S vlastnostmi z Unicode je to snadné: [\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}].
Rozšifrujme to. Vytváříme si vlastní množinu podobnou \w, která obsahuje znaky s následujícími vlastnostmi v Unicode:
Alphabetic(Alpha) – písmena,Mark(M) – diakritická znaménka,Decimal_Number(Nd) – číslice,Connector_Punctuation(Pc) – podtržítko'_'a podobné znaky,Join_Control(Join_C) – dva speciální kódy200ca200dpoužívané v ligaturách, např. v arabštině.
Příklad použití:
let rv = /[\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]/gu;
let řetězec = `Čau 你好 12`;
// najde všechna písmena a číslice:
alert( řetězec.match(rv) ); // Č,a,u,你,好,1,2
Tento vzor můžeme samozřejmě měnit: přidávat nebo odstraňovat vlastnosti z Unicode. Tyto vlastnosti jsou podrobněji probrány v článku Unicode: příznak „u“ a třída \p{...}.
Vlastnosti z Unicode p{…} nejsou implementovány v IE. Pokud je opravdu potřebujeme, můžeme použít knihovnu XRegExp.
Nebo jen použít rozsahy znaků v jazyce, který nás zajímá, např. [а-я] pro písmena kyrilice.
Vylučovací rozsahy
Kromě normálních rozsahů existují také „vylučovací“ rozsahy, které vypadají takto: [^…].
Jsou na začátku označeny znakem stříšky ^ a odpovídá jim každý znak kromě uvedených.
Například:
[^aeyo]– jakýkoli znak kromě'a','e','y'nebo'o'.[^0-9]– jakýkoli znak kromě číslice, totéž jako\D.[^\s]– jakýkoli nemezerový znak, totéž jako\S.
Následující příklad hledá všechny znaky kromě písmen, číslic a mezer:
alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // @ a .
Únikové znaky v […]
Když chceme najít přímo speciální znak, obvykle před ním musíme uvést únikový znak \.. Pokud potřebujeme zpětné lomítko, používáme \\ a podobně.
V hranatých závorkách můžeme používat převážnou většinu speciálních znaků bez únikového znaku:
- Symboly
. + ( )nikdy nepotřebují únikový znak. - Pomlčka
-nepotřebuje únikový znak na začátku a na konci (kde nedefinuje rozsah). - Stříška
^potřebuje únikový znak jen na začátku (kde znamená vyloučení). - Uzavírací hranatá závorka
]potřebuje únikový znak vždy (pokud ji potřebujeme hledat).
Jinými slovy, všechny speciální znaky jsou povoleny bez únikového znaku kromě situace, kdy mají v hranatých závorkách nějaký zvláštní význam.
Tečka . uvnitř hranatých závorek znamená skutečnou tečku. Vzor [.,] najde jeden z uvedených znaků: buď tečku, nebo čárku.
V následujícím příkladu RV [-().^+] hledá jeden ze znaků -().^+:
// Nepotřebujeme únikový znak
let rv = /[-().^+]/g;
alert( "1 + 2 - 3".match(rv) ); // Najde +, -
…Když se však rozhodnete „pro všechny případy“ únikový znak uvést, ničemu tím neublížíte:
// Únikový znak všude
let rv = /[\-\(\)\.\^\+]/g;
alert( "1 + 2 - 3".match(rv) ); // také to funguje: +, -
Rozsahy a příznak „u“
Jestliže jsou v množině zástupné páry, je třeba uvést příznak u, aby fungovaly správně.
Podívejme se například na [𝒳𝒴] v řetězci 𝒳:
alert( '𝒳'.match(/[𝒳𝒴]/) ); // zobrazí podivný znak, např. [?]
// (hledání bylo provedeno nesprávně, vrátila se polovina znaku)
Výsledek není správný, protože regulární výrazy standardně „neznají“ zástupné páry.
Motor regulárních výrazů si myslí, že [𝒳𝒴] nejsou dva, ale čtyři znaky:
- levá polovina
𝒳(1), - pravá polovina
𝒳(2), - levá polovina
𝒴(3), - pravá polovina
𝒴(4).
Jejich kódy můžeme vidět následovně:
for(let i=0; i<'𝒳𝒴'.length; i++) {
alert('𝒳𝒴'.charCodeAt(i)); // 55349, 56499, 55349, 56500
};
Výše uvedený příklad tedy najde a zobrazí levou polovinu znaku 𝒳.
Jestliže přidáme příznak u, chování bude korektní:
alert( '𝒳'.match(/[𝒳𝒴]/u) ); // 𝒳
Obdobná situace nastane, když budeme hledat rozsah, například [𝒳-𝒴].
Pokud zapomeneme uvést příznak u, nastane chyba:
'𝒳'.match(/[𝒳-𝒴]/); // Error: Invalid regular expression
Důvodem je, že bez příznaku u se zástupné páry považují za dva znaky, takže [𝒳-𝒴] je interpretováno jako [<55349><56499>-<55349><56500>] (každý zástupný pár je nahrazen svými kódy). Nyní jasně vidíme, proč je rozsah 56499-55349 neplatný: jeho počáteční kód 56499 je větší než koncový 55349. To je formální příčina chyby.
S příznakem u bude vzor fungovat správně:
// hledá znaky od 𝒳 do 𝒵
alert( '𝒴'.match(/[𝒳-𝒵]/u) ); // 𝒴
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…)