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

Answer from Wiktor Stribiżew on Stack Overflow
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).

🌐
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
Discussions

java - A regex to match a substring that isn't followed by a certain other substring - Stack Overflow
I need a regex that will match blahfooblah but not blahfoobarblah I want it to match only foo and everything around foo, as long as it isn't followed by bar. I tried using this: foo.*(? More on stackoverflow.com
🌐 stackoverflow.com
Regex match pattern not preceded by either of two expressions

Are they actually the same length as foo and bar are - because it should work in that case.

>>> import re
>>> text = 'foo bar\nbaz bar\nblub bar'
>>> re.findall('\S+(?<!foo|baz) bar', text)
['blub bar']

The 3rd party regex module does support variable length (among other things)

>>> import regex as re
>>> re.findall('\S+(?<!foo|blub) bar', text)
['baz bar']

Alternative you could just capture all the matches and do the filtering yourself in code.

More on reddit.com
🌐 r/learnpython
5
5
September 17, 2019
regex - RegExp exclusion, looking for a word not followed by another - Stack Overflow
I am trying to search for all occurrences of "Tom" which are not followed by "Thumb". I have tried to look for Tom ^((?!Thumb).)*$ but I still get the lines that match to Tom Thumb. More on stackoverflow.com
🌐 stackoverflow.com
RegEx pattern with not followed by - Stack Overflow
I want to match only first file path, which not contains word Thumbnails. I use "not-followed by pattern" but it doesn`t work. Could some one take a look and tell me where is my mistake? Here is my... More on stackoverflow.com
🌐 stackoverflow.com
🌐
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 ...
Top answer
1 of 5
194

Try:

/(?!.*bar)(?=.*foo)^(\w+)$/

Tests:

blahfooblah            # pass
blahfooblahbarfail     # fail
somethingfoo           # pass
shouldbarfooshouldfail # fail
barfoofail             # fail

Regular expression explanation

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    bar                      'bar'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    foo                      'foo'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Other regex

If you only want to exclude bar when it is directly after foo, you can use

/(?!.*foobar)(?=.*foo)^(\w+)$/

Edit

You made an update to your question to make it specific.

/(?=.*foo(?!bar))^(\w+)$/

New tests

fooshouldbarpass               # pass
butnotfoobarfail               # fail
fooshouldpassevenwithfoobar    # pass
nofuuhere                      # fail

New explanation

(?=.*foo(?!bar)) ensures a foo is found but is not followed directly bar

2 of 5
64

To match a foo following by something that doesn't start with bar, try

foo(?!bar)

Your version with negative lookbehind is effectively "match a foo followed by something that doesn't end in bar". The .* matches all of barblah, and the (?<!bar) looks back at lah and checks that it doesn't match bar, which it doesn't, so the whole pattern matches.

🌐
Regular-Expressions.info
regular-expressions.info › lookaround.html
Regex Tutorial: Lookahead and Lookbehind Zero-Length Assertions
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. Inside the lookahead, we have the trivial regex u.
Find elsewhere
🌐
TutorialsTeacher
tutorialsteacher.com › regex › lookarounds
Lookarounds in Regex
The following finds any word that is not followed by a question mark ? character. ... In the above example, \b is used for a word boundary, \w+ is used for one or more word characters, so \b\w+\b finds the whole word. Pattern, \? uses escape sequence \ for ? because it is a metacharacter in regex ...
🌐
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".
🌐
O'Reilly
oreilly.com › library › view › regular-expressions-cookbook › 9781449327453 › ch05s06.html
5.6. Find Any Word Not Preceded by a Specific Word - Regular Expressions Cookbook, 2nd Edition [Book]
August 27, 2012 - The following regexes use negative lookbehind, ‹(?<!⋯)›. Unfortunately, the regex flavors covered by this book differ in what kinds of patterns they allow you to place within lookbehind. The solutions therefore end up working a bit differently in each case. Read on to the section of this recipe for further details. ... JavaScript and Ruby 1.8 do not support lookbehind at all, even though they do support lookahead.
Authors   Jan GoyvaertsSteven Levithan
Published   2012
Pages   609
🌐
Notepad++ Community
community.notepad-plus-plus.org › topic › 23570 › regex-with-negative-lookahead
Regex with Negative Lookahead | Notepad++ Community
October 6, 2022 - It’s very important to unsderstand that regex engines search, BY ALL MEANS a match of the current regex against the INPUT text ... As we use the simple \R? syntax, backtracking is possible. So : First, the regex engine matches the <section class="lyrics"> part, followed with the line-break chars \r\n · But as it’s followed with the <div class="audio"> string, it does not satisfy the negative look-ahead (?!<div class="audio">)