Asercja pozytywna i negatywna w wyrażeniach regularnych JavaScript
Czasami trzeba rozwiązać zadanie tego typu: znaleźć
ciąg 'aaa' i zamienić go na '!',
ale tylko jeśli po 'aaa' znajduje się
'x', przy czym samego 'x'
nie zamieniamy. Jeśli spróbujemy rozwiązać to zadanie
'bezpośrednio', nic nam nie wyjdzie:
'aaax baaa'.replace(/aaax/g, '!'); // zwróci '! baaa', a chcieliśmy '!x baaa'
Asercja do przodu (lookahead)
Aby rozwiązać zadanie, potrzebny jest sposób na powiedzenie,
że 'x' nie powinno być zastępowane. Robi się
to za pomocą specjalnych nawiasów (?= ),
które tylko sprawdzają, ale nie pobierają.
Te nawiasy nazywane są asercją pozytywną do przodu.
Pozytywna - ponieważ 'x'
(w naszym przypadku) musi być - tylko wtedy
nastąpi zamiana.
Zastosujmy te nawiasy do rozwiązania naszego zadania:
'aaax aaab'.replace(/aaa(?=x)/g, '!'); // zwróci '!x aaab'
Istnieje też asercja negatywna do przodu
- (?! ) - która, przeciwnie, mówi, że
czegoś nie powinno być. W następnym przykładzie
zamiana nastąpi tylko, jeśli po 'aaa'
NIE ma 'x':
'aaax aaab'.replace(/aaa(?!x)/g, '!'); // zwróci 'aaax !b'
Asercja do tyłu (lookbehind)
Analogicznie istnieje asercja pozytywna do tyłu
- (?<= ). W następnym
przykładzie zamiana nastąpi tylko, jeśli przed
'aaa' znajduje się 'x':
'xaaa'.replace(/(?<=x)aaa/g, '!'); // zwróci 'x!'
Jest też asercja negatywna do tyłu
- (?<! ). W następnym przykładzie zamiana
nastąpi tylko, jeśli przed 'aaa'
nie znajduje się 'x':
'baaa'.replace(/(?<!x)aaa/g, '!'); // zwróci 'b!'
Zadania praktyczne
Dany jest ciąg zawierający nazwy funkcji:
let str = 'func1() func2() func3()';
Pobierz tablicę nazw funkcji z ciągu.
Dany jest ciąg z tagiem:
let str = '<a href="" class="eee" id="zzz">';
Pobierz tablicę nazw atrybutów tego tagu.
Dany jest ciąg ze zmiennymi:
let str = '$aaa $bbb $ccc xxxx';
Pobierz podciągi, przed którymi znajduje się znak dolara.