Regex to exclude a substring

Viewed 264

I am trying to match a param string but exclude any matches when a substring is present.

From my limited regex knowledge this should work to exlude any string containing "porcupine", but it's not. What am I doing wrong?

(\/animal\?.*(?!porcupine).*color=white)

Expected Outcome

| string                                          | matches? |
| ----------------------------------------------- | -------- |
| /animal?nose=wrinkly&type=porcupine&color=white | false    |
| /animal?nose=wrinkly&type=puppy&color=white     | true     |

Actual Outcome

| string                                          | matches? |
| ----------------------------------------------- | -------- |
| /animal?nose=wrinkly&type=porcupine&color=white | true     |
| /animal?nose=wrinkly&type=puppy&color=white     | true     |
3 Answers

The .* searches anything for any number of times, greedily. So you could replace it with a literal search:

(\/animal\?nose=wrinkly\&type=(?!porcupine).*color=white)

See example here: https://regex101.com/r/HJiM2N/1

This may seem overly verbose but it is actually relatively efficient in the number of steps:

(?!\/animal.*?porcupine.*?color)\/animal\?.*color=white

See Regex Demo

If the input string consists of only one and only one occurrence of what you are trying to match and nothing else, then just use the following to ensure that porcupine does not occur anywhere in the input string:

(?!.*porcupine)\/animal\?.*color=white

The code:

import re

tests = [
    '/animal?nose=wrinkly&type=porcupine&color=white',
    '/animal?nose=wrinkly&type=puppy&color=white'
]

rex = r'(?!\/animal.*?porcupine.*?color)\/animal\?.*color=white'

for test in tests:
    m = re.search(rex, test)
    print(test, 'True' if m else 'False')

Prints:

/animal?nose=wrinkly&type=porcupine&color=white False
/animal?nose=wrinkly&type=puppy&color=white True
Related