Regulární výrazy (regulární výrazy) jsou samy o sobě výzvou. Mně to vždy trvá pár minut, než pochopím, co konkrétní regulární výraz dělá. Jsou kouzelné a o jejich užitečnosti není pochyb.
Dnes jsem si dal nedělní ranní kávu a propracoval se přes slide deck „Co je nového v ES2018“ od Benedikta Meurera a Mathiase Bynense.
Na těchto snímcích je tolik užitečných informací. Kromě nových jazykových funkcí, jako jsou asynchronní iterace, vlastnosti šíření objektů a pojmenované skupiny zachycení v regulárních výrazech (🎉), pokrývají výhledy regulárních výrazů (a nadcházející vzhled).
Tu a tam mi cestu zkříží předpovědi v regulárních výrazech JavaScriptu a musím přiznat, že jsem je nikdy nemusel používat, ale nyní je protějšek hledá budou také v jazyce, takže jsem se rozhodl přečíst si nějakou dokumentaci a konečně se naučit, co jsou tyto regex lookaheads a lookbehind.
Regulační vyhledávání v JavaScriptu
Můžete definovat vzory, které se shodují pouze tehdy, když je následuje nebo nenásleduje jiný vzor s předběžnými informacemi.
Článek MDN o regulárních výrazech popisuje dva různé typy předběžných dotazů v regulárních výrazech.
Pozitivní a negativní výhledy:
x(?=y)
– pozitivní výhled (odpovídá „x“, když za ním následuje „y“)x(?!y)
– negativní výhled (odpovídá 'x', pokud není následováno 'y')
Zachycené skupiny v JavaScriptu – podobně vypadající společníci
No dobře... x(?=y)
– to je složitá syntaxe, pokud se mě ptáte. Co mě zpočátku zmátlo, je, že obvykle používám ()
pro zachycené skupiny nebo nezachycující skupiny ve výrazech JavaScript.
Podívejme se na příklad zachycené skupiny:
const regex = /\w+\s(\w+)\s\w+/;
regex.exec('eins zwei drei');
// ['eins zwei drei', 'zwei']
// /\
// ||
// captured group
// defined with
// (\w+)
Regulární výraz výše zachycuje slovo (zwei
v tomto případě), který je obklopen mezerami a dalším slovem.
Přehledy regulárních výrazů nejsou jako zachycené skupiny
Podívejme se na typický příklad, který najdete, když si přečtete o předběžných dotazech v regulárních výrazech JavaScriptu.
// use positive regex lookahead
const regex = /Max(?= Mustermann)/;
regex.exec('Max Mustermann');
// ['Max']
regex.exec('Max Müller');
// null
Tento příklad odpovídá Max
vždy, když za ním následuje mezera a Mustermann
jinak se neshoduje a vrátí null
. Pro mě je zajímavé, že odpovídá pouze Max
a ne vzor definovaný ve výhledu ((?= Mustermann)
). Toto vyloučení se může po práci s regulárními výrazy zdát divné, ale když se nad tím zamyslíte, je to rozdíl mezi výhledy a skupinami. Pomocí předběžných dotazů můžete testovat řetězce proti vzorům, aniž byste je zahrnuli do výsledné shody.
Příklad "Max Mustermann" není příliš užitečný, ale pojďme se ponořit do pozitivních a negativních výhledů s případem použití v reálném světě.
Pozitivní regulární výraz v JavaScriptu
Předpokládejme, že máte dlouhý řetězec Markdown, který obsahuje seznam lidí a jejich preferencí v jídle. Jak byste přišli na to, kteří lidé jsou vegani, když je všechno jen dlouhý řetězec?
const people = `
- Bob (vegetarian)
- Billa (vegan)
- Francis
- Elli (vegetarian)
- Fred (vegan)
`;
// use positive regex lookahead
const regex = /-\s(\w+?)\s(?=\(vegan\))/g;
// |----| |-----------|
// / \
// more than one \
// word character positive lookahead
// but as few as => followed by "(vegan)"
// possible
let result = regex.exec(people);
while(result) {
console.log(result[1]);
result = regex.exec(people);
}
// Result:
// Billa
// Fred
Pojďme se rychle podívat na regulární výraz a pokusit se jej formulovat slovy.
const regex = /-\s(\w+?)\s(?=\(vegan\))/g;
Dobře... pojďme na to!
Negativní/negující regulární výrazy v JavaScriptu
Na druhou stranu, jak byste přišli na to, kdo není vegan?
const people = `
- Bob (vegetarian)
- Billa (vegan)
- Francis
- Elli (vegetarian)
- Fred (vegan)
`;
// use negative regex lookahead
const regex = /-\s(\w+)\s(?!\(vegan\))/g;
// |---| |-----------|
// / \
// more than one \
// word character negative lookahead
// but as few as => not followed by "(vegan)"
// possible
let result = regex.exec(people);
while(result) {
console.log(result[1]);
result = regex.exec(people);
}
// Result:
// Bob
// Francis
// Elli
Pojďme se rychle podívat na regulární výraz a zkusme jej také formulovat slovy.
const regex = /-\s(\w+)\s(?!\(vegan\))/g;
Regexové předpovědi budou mít brzy společnost od pohledu zezadu
Lookbehinds bude fungovat stejně, ale u vzorů vedoucích. Lookaheads zvažují vzory po odpovídající části zatímco hledí zvažují vzory dříve . Lookbehinds jsou v Chrome dnes podporovány. Budou také k dispozici jako pozitivní lookbehind x(?<=y)
a negativní lookbehind x(?<!y)
.
Když otočíme vzorové řetězce a upravíme regulární výraz tak, aby používal lookbehinds, vše stále funguje.
const people = `
- (vegetarian) Bob
- (vegan) Billa
- Francis
- (vegetarian) Elli
- (vegan) Fred
`;
// use positive regex lookbehind
const regex = /(?<=\(vegan\))\s(\w+)/g;
// |------------| |---|
// / \__
// positive lookbehind \
// => following "(vegan)" more than one
// word character
// but as few as possible
let result = regex.exec(people);
while(result) {
console.log(result[1]);
result = regex.exec(people);
}
// Result:
// Billa
// Fred
Poznámka:Obvykle doporučuji RegExr pro pohrávání si s regulárními výrazy, ale lookbehinds zatím nejsou podporovány.
Další zdroje
Pokud vás zajímají další špičkové funkce, podívejte se na snímky Mathiase a Benedikta o nových funkcích přicházejících do JavaScriptu, protože přijdou mnohem zajímavější věci.
Další poznámka na okraj:Pokud vyvíjíte v prohlížeči, nezapomeňte nejprve zkontrolovat podporu lookbehinds. V době psaní tohoto článku nejsou ve Firefoxu podporovány.
Abychom si zapamatovali syntaxi pro dopředný pohled a dopředný pohled, vytvořil jsem o tom rychlý cheat sheet.