Positive and negative lookaround in JavaScript regexes
Sometimes you need to solve a problem
of this type: find the string 'aaa'
and replace it with '!', but only
if after 'aaa'⁅/s ⁆ is ,
while 'x''x' itself is not replaced. If
we try to solve the problem 'head-on',
then nothing will come of it:
'aaax baaa'.replace(/aaax/g, '!'); // returns '! baaa', but we wanted '!x baaa'
Lookahead
To solve the problem, we need a way
to say that 'x' should not
be replaced. This is done with the
special parentheses (?= ),
which just look at, but don't take
with them.
These parentheses are called
positive lookahead. Positive
- since 'x' (in our case)
should be - only then replacement
will occur.
Let's use these parentheses to solve our problem:
'aaax aaab'.replace(/aaa(?=x)/g, '!'); // returns '!x aaab'
There is also negative lookahead
- (?! ) - on the contrary, it
says that something should not be. In
the following example, the replacement
will only occur if 'aaa' is
NOT followed by 'x':
'aaax aaab'.replace(/aaa(?!x)/g, '!'); // returns 'aaax !b'
Lookbehind
Similarly, there is
positive lookbehind - (?<= ). In
the following example, the replacement
will only occur if 'aaa' is
preceded by 'x':
'xaaa'.replace(/(?<=x)aaa/g, '!'); // returns 'x!'
And there is also
negative lookbehind - (?<! ). In
the following example, the replacement
will only occur if 'aaa' is
not preceded by 'x':
'baaa'.replace(/(?<!x)aaa/g, '!'); // returns 'b!'
Practical tasks
Given a string containing function names:
let str = 'func1() func2() func3()';
Get an array of the function names from the string.
Given a string with a tag:
let str = '<a href="" class="eee" id="zzz">';
Get an array of attribute names for this tag.
Given a string with variables:
let str = '$aaa $bbb $ccc xxxx';
Get substrings preceded by a dollar sign.