'How do I perform a negative lookaround search
I'm looking for all instances of a certain character in a string of text except for when it is both prefixed and suffixed a certain way.
A simple example of this would be to find all instances of "a" in the string "I am a cat in a hat in a car" except where it appears in the word "cat":
I am acatin a hat in a car
Combining a negative lookbehind assertion and a negative lookahead assertion doesn't seem to work because it fails when either of the assertions are triggered rather than only when both are triggered.
Using a regex to find "a"s but ignore "ca"s ignores the word "car":
/(?<!c)a/g
I am acatin a hat in acar❌
Using a regex to find "a"s but ignore "at"s ignores the word "hat":
/a(?!t)/g
I am acatin ahat❌ in a car
Combining the two ignores both "car" and "hat":
/(?<!c)a(?!t)/g
I am acatin ahat❌ in acar❌
Regex seems to NOR the two assertions, is it possible to NAND them?
Solution 1:[1]
You can nest the lookarounds, matching a and assert that to the left is not ca that is followed by t and use word boundaries \b to prevent a partial word match.
a(?<!\bca(?=t\b))
Or written with the lookbehind first, asserting not c to the left:
(?<!\bc(?=at\b))a
Solution 2:[2]
You can use the exception token [^...] and alternate between both positive lookarounds: /(?<=[^c])a|a(?=[^r])/g.
By setting two exceptions in an OR, it's like a NAND gate and 2 NOT gates:
They both have to be true in order for it to be no match 1 and 1 => 0
Only one exception needs to be false so there is a match 0 and 1 => 1
If both are false then there's a match as well 0 and 0 => 1
| Segment | Meaning |
|---|---|
(?<=[^c])a |
Match literal "a" if there is anything BUT a literal "c" before it |
| |
OR |
a(?=[^r]) |
Match literal "a" if there is anything BUT a literal "r" after it |
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
