12. června 2026

Množiny a rozsahy [...]

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“.

Znakové třídy jsou zkratky určitých množin znaků

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ódy 200c a 200d použí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 nejsou podporovány v IE

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:

  1. levá polovina 𝒳 (1),
  2. pravá polovina 𝒳 (2),
  3. levá polovina 𝒴 (3),
  4. 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) ); // 𝒴

Úlohy

Máme regulární výraz /Java[^script]/.

Najde shodu v řetězci Java? A v řetězci JavaScript?

Odpovědi zní: ne, ano.

  • V řetězci Java nenalezne nic, neboť [^script] znamená „jakýkoli znak kromě uvedených“. Regulární výraz tedy bude hledat řetězec "Java" následovaný jedním takovým symbolem, ale po něm nenásleduje žádný symbol, nýbrž konec řetězce.

    alert( "Java".match(/Java[^script]/) ); // null
  • Ano, protože části [^script] odpovídá znak "S", který není jedním ze script. Protože tento RV rozlišuje malá a velká písmena (nemá příznak i), bude "S" považovat za jiný znak než "s".

    alert( "JavaScript".match(/Java[^script]/) ); // "JavaS"

Čas může být ve formátu hodiny:minuty nebo hodiny-minuty. Hodiny i minuty mají vždy 2 číslice: 09:00 nebo 21-30.

Napište regulární výraz, který najde čas:

let rv = /váš RV/g;
alert( "Snídaně v 09:00. Večeře v 21-30".match(rv) ); // 09:00, 21-30

P.S. V této úloze předpokládáme, že čas je vždy správně, nemusíte odfiltrovávat nesprávné řetězce jako “45:67”. Později si poradíme i s nimi.

Odpověď: \d\d[-:]\d\d.

let rv = /\d\d[-:]\d\d/g;
alert( "Snídaně v 09:00. Večeře v 21-30".match(rv) ); // 09:00, 21-30

Prosíme všimněte si, že pomlčka '-' má v hranatých závorkách speciální význam, ale jen mezi jinými znaky a ne na začátku nebo na konci, takže před ní nemusíme uvádět únikový znak.

Mapa tutoriálu

Komentáře

přečtěte si před komentováním…
  • Máte-li návrhy na zlepšení, vytvořte prosím issue na GitHubu nebo pull request místo komentáře.
  • Pokud v článku něčemu nerozumíte, napište prosím, čemu přesně a na kterém místě.
  • Pro vložení několika slov kódu použijte značku <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…)