Home > OS >  How do I perform a negative lookaround search
How do I perform a negative lookaround search

Time:04-27

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 a cat in 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 a cat in a hat in a car

Using a regex to find "a"s but ignore "at"s ignores the word "hat":

/a(?!t)/g
I am a cat in a hat❌ in a car

Combining the two ignores both "car" and "hat":

/(?<!c)a(?!t)/g
I am a cat in a hat❌ in a car

Regex seems to NOR the two assertions, is it possible to NAND them?

CodePudding user response:

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))

Regex demo

Or written with the lookbehind first, asserting not c to the left:

(?<!\bc(?=at\b))a

Regex demo

CodePudding user response:

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:

  1. They both have to be true in order for it to be no match  1 and 1 => 0

  2. Only one exception needs to be false so there is a match 0 and 1 => 1

  3. 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

https://regex101.com/r/CWV0ff/1

  • Related