Given the situation that you have to replace a specific term in your code base, but e.g. only those that are not preceded by a particular term. How would you search for those? One way is manually picking the matches that have to be replaced. Another way would be using regular expression and its negative lookbehind. With the help of regular expressions and lookaround it is possible to exclude patterns before and after a math or require the presence of a pattern.
Lookbehind
As already stated, with the help of lookbehind, the search looks at what is before the search term (as viewed from ltr languages).
Negative lookbehind
It is easier to memorize this as follows: The search looks back at what already has been processed. In case of a negative lookbehind, matches are excluded.
For example, (?<!hello)world
matches all occurrences of “world” that are not preceded by a “hello”.
Positive lookbehind
Instead of excluding matches that are preceded by a defined term, it is also possible to exclude all other matches. This comes in handy if one wants to replace only part of the matches, without using groups in both, the search and the replacement expressions.
(?<=hello)world
matches all world that are preceded by a “hello”. Note that only the “world” in “helloworld” is matched.
Using groups to replace “world” with “John” the search expression would have to be (hello)(world)
with a replacement expression $1John
Lookahead
A lookahead search expression looks at what is after the search term.
Negative lookahead
hello(?!world)
matches a “hello” not followed by a “world”.
Positive lookahead
hello(?=world)
matches a “hello” immediately followed by a “world”.
A lesson learnt
While I was writing this, I actually didn’t think that a positive lookbehind would be a thing. Why would this be useful? The pattern of the positive lookbehind is matched, but without being marked as result. This could save some time of having to use a group to exclude the first or last part (or middle part) of a match in find and replace scenarios.
Searching (?<=hello )world
and replacing with John
is much faster and easier to comprehend, than searching for (hello )(world)
and replacing the matches with $1John
. This is just a simplified example, but working with groups can become quite messy.
Further resources and references
Most of the following text is better described here, I just extracted a few key points that interest me from there and adapt the examples to my own needs. I highly recommend to also check out those two sites: