Use negative look-arounds:

re.findall(r"(?<![\da-z])[a-z]+(?![\da-z])", string.lower())

This matches lower-case letters that are not immediately preceded or followed by more letters or digits.

Demo:

>>> import re
>>> string = "ts0060_LOD-70234_lr2_billboards_rgba_over_s3d_lf_v5_2Kdciufa_lnh"
>>> re.findall(r"(?<![\da-z])[a-z]+(?![\da-z])", string.lower())
['lod', 'billboards', 'rgba', 'over', 'lf', 'lnh']
Answer from Martijn Pieters on Stack Overflow
Discussions

python - regex match if not followed by pattern - Stack Overflow
I need to match string like: RHS numberXnumberXnumber contained in strings like these: (all numbers can have the decimal part or not) foo RHS 100x100x10 foo foo RHS 100.0x100x10 foo foo RHS ... More on stackoverflow.com
🌐 stackoverflow.com
December 17, 2017
python - Regular expression to search for a string1 that is never followed by string2 - Stack Overflow
2 How can I check if every substring of four zeros is followed by at least four ones using regular expressions? ... 1 A regular expression to match a keyword that does not have that same word appear before another keyword · 5 How can I find a string that contains any between two regular expressions except for a certain regex in python... More on stackoverflow.com
🌐 stackoverflow.com
Python Regex: Match a string not preceded by or followed by a word with digits in it - Stack Overflow
I would like to have a Regex in Python to replace a string not preceded by or followed by a word with digits in it. i.e. For the following sentence, Today is 4th April. Her name is April. Tomor... More on stackoverflow.com
🌐 stackoverflow.com
March 30, 2020
regex - Find 'word' not followed by a certain character - Stack Overflow
This regex matches word substring and (?!@) makes sure there is no @ right after it, and if it is there, the word is not returned as a match (i.e. the match fails). ... Negative lookahead is indispensable if you want to match something not followed by something else. More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 2
2

It can be done with Pypi regex library that supports variable-length lookbehind.

import regex

str = 'Today is 4th April. Her name is April. Tomorrow is April 5th.'
res = regex.sub(r'(?<!\d[a-z]* )April(?! [a-z]*\d)', 'PERSON', str)
print(res)

Output:

Today is 4th April. Her name is PERSON. Tomorrow is April 5th.

Explanation:

(?<!\d[a-z]* )      # negative lookbehind, make sure we haven't a digit followed by 0 or more letters and a space before
April               # literally
(?! [a-z]*\d)       # negative lookahead, make sure we haven't a space, 0 or more letters and a digit after

Update with re module:

import re

str = 'Today is 4th April. Her name is April. Tomorrow is April 5th.'
res = re.sub(r'(\b[a-z]+ )April(?! [a-z]*\d)', '\g<1>PERSON', str)
print(res)
2 of 2
1

This is one regex you could use:

(?:^\s+|[^\w\s]+\s*|\b[^\d\s]+\s+)(April)\b(?!\s*\w*\d)

with the case-indifferent flag set. The target word is captured in capture group 1.

Demo

Python's regex engine performs the following operations:

(?:           # begin non-cap grp
  ^           # match beginning of line
  \s*         # match 0+ whitespace characters
  |           # or
  [^\w\s]+    # match 1+ chars other than word chars and whitespace
  \s*         # match 0+ whitespace chars
  |           # or
  \b          # match word break
  [^\d\s]+    # match 1+ chars other than digits and whitespace
  \s+         # match 1+ whitespace chars
)             # end non-cap grp  
(April)       # match 'April' in capture group
\b            # match word break
(?!           # begin negative lookahead
  \s*         # match 0+ whitespace chars         
  \w*         # match 0+ word chars
  \d          # match a digit
)             # end negative lookahead

The approach I've taken was to specify what may precede "April" and why may not follow it. I could not specify what cannot precede "April" as that would require a negative lookbehind, which is not supported by Python's regex engine.

I've assume that "April" may:

  • be at the beginning of the string, possibly followed by spaces;
  • be preceded by a character that is neither a word character nor a space, possibly followed by spaces; or
  • be preceded by a word containing no digits, possibly followed by spaces.

I've also assumed that "April" is followed by a word break which may not be followed by a word containing a digit, possibly preceded by spaces.

🌐
Finxter
blog.finxter.com › home › learn python blog › how to find all lines not containing a regex in python?
How to Find All Lines Not Containing a Regex in Python? - Be on the Right Side of Change
June 19, 2022 - You search for a position where neither 'hi' is in the lookahead, nor does the question mark character follow immediately. This time, we consume an arbitrary character, so the resulting match is the character 'i'. Summary: You’ve learned that you can match all lines that do not match a certain regex by using the lookahead pattern ((?!regex).)*.
Find elsewhere
Top answer
1 of 1
234

The (?!@) negative look-ahead will make word match only if @ does not appear immediately after word:

word(?!@)

If you need to fail a match when a word is followed with a character/string somewhere to the right, you may use any of the three below

word(?!.*@)       # Note this will require @ to be on the same line as word
(?s)word(?!.*@)   # (except Ruby, where you need (?m)): This will check for @ anywhere...
word(?![\s\S]*@)  # ... after word even if it is on the next line(s)

See demo

This regex matches word substring and (?!@) makes sure there is no @ right after it, and if it is there, the word is not returned as a match (i.e. the match fails).

From Regular-expressions.info:

Negative lookahead is indispensable if you want to match something not followed by something else. When explaining character classes, this tutorial explained why you cannot use a negated character class to match a q not followed by a u. Negative lookahead provides the solution: q(?!u). The negative lookahead construct is the pair of parentheses, with the opening parenthesis followed by a question mark and an exclamation point.

And on Character classes page:

It is important to remember that a negated character class still must match a character. q[^u] does not mean: "a q not followed by a u". It means: "a q followed by a character that is not a u". It does not match the q in the string Iraq. It does match the q and the space after the q in Iraq is a country. Indeed: the space becomes part of the overall match, because it is the "character that is not a u" that is matched by the negated character class in the above regexp. If you want the regex to match the q, and only the q, in both strings, you need to use negative lookahead: q(?!u).

🌐
Python Tutorial
pythontutorial.net › home › python regex › python regex lookahead
Python Regex Lookahead
September 19, 2022 - Use the negative regex lookahead X(?!Y) that matches X only if it is not followed by Y.
🌐
Regex Tester
regextester.com › 107904
Regex to match string NOT followed by [ - Regex Tester/Debugger
Url checker with or without http:// ... string not containing string Check if a string only contains numbers Only letters and numbers Match elements of a url date format (yyyy-mm-dd) Url Validation Regex | Regular Expression - Taha Match an email address Validate an ip address nginx test Extract String Between Two STRINGS special characters check match whole word Match or Validate phone number Match anything enclosed by square ...
🌐
Squash
squash.io › how-to-regex-regex-not-match
Using Regular Expressions to Exclude or Negate Matches
September 12, 2023 - The string.match() function returns an array of all matches, which in this case are all the word characters that are not followed by "123" in the string "Hello123World". The pipe (|) symbol can also be used to perform a "not match" operation by specifying multiple patterns separated by the pipe symbol. This allows you to match any pattern except the ones specified. For example, the regex pattern ^(?!dog$|cat$) matches any word that is not exactly "dog" or "cat".
🌐
Reddit
reddit.com › r/regex › not preceded by either or
r/regex on Reddit: Not preceded by either or
September 17, 2019 -

I'm a RegEx Noob and I'm using Python to match a string not preceded by either of two expression.

So the regex should not match

foo bar
baz bar

but should match bar in

blub bar

I know how to match a string not preceded by something. That would be:

(?<!foo )bar

But I can't use

(?<!foo|baz )bar

because Python doesn't support variable width lookbehinds. From StackOverflow I learned that I could invert my string and and use a negative lookahead, but isn't there a less weird solution in my case?

oof(?! rab| zad)
🌐
Python documentation
docs.python.org › 3 › library › re.html
re — Regular expression operations — Python 3.14.6 ...
May 25, 2026 - This is called a lookahead assertion. For example, Isaac (?=Asimov) will match 'Isaac ' only if it’s followed by 'Asimov'. ... Matches if ... doesn’t match next. This is a negative lookahead assertion. For example, Isaac (?!Asimov) will match 'Isaac ' only if it’s not followed by 'Asimov'.
🌐
O'Reilly
oreilly.com › library › view › regular-expressions-cookbook › 9780596802837 › ch05s05.html
5.5. Find Any Word Not Followed by a Specific Word - Regular Expressions Cookbook [Book]
May 22, 2009 - You want to match any word that is not immediately followed by the word cat, ignoring any whitespace, punctuation, or other nonword characters that appear in between.
Authors   Jan GoyvaertsSteven Levithan
Published   2009
Pages   510
🌐
Regular-Expressions.info
regular-expressions.info › lookaround.html
Regex Tutorial: Lookahead and Lookbehind Zero-Length Assertions
When explaining character classes, ... a q not followed by a u. Negative lookahead provides the solution: q(?!u). The negative lookahead construct is the pair of parentheses, with the opening parenthesis followed by a question mark and an exclamation point. Inside the lookahead, we have the trivial regex ...