100

What is the regular expression to search for word string that is not followed by the @ symbol?

For example:

mywordLLD         OK
myword.dff        OK
myword@ld         Exclude
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
user836026
  • 10,608
  • 15
  • 73
  • 129
  • 1
    `word[^@]`? It covers all the examples; it doesn't cover a line which ends with `word`; for that, you'd need `word($|[^@])` instead. – Jonathan Leffler Jul 03 '15 at 08:08
  • 1
    @JonathanLeffler You've been here long enough to know to post answers as answers, not as comments. :) Anyway, that also includes the next character in the match, so for instance `s/word[^@]/otherword/g` won't have the same effect as stribizhev's answer of using a lookahead. –  Jul 03 '15 at 08:09
  • **See Also**: [A regex to match a substring that isn't followed by a certain other substring](https://stackoverflow.com/q/2631010/1366033) – KyleMit Dec 21 '21 at 13:28

1 Answers1

191

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

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 2
    For R users, be sure to add `perl = TRUE` to your command, like `gsub("word(?!@)", "", obj, perl = TRUE)`. Otherwise it will throw an error 'Invalid regexp'. – MS Berends Mar 18 '19 at 10:26
  • 3
    @xwhitelight You are just not looking at the right place, see [Why is this regex using lookbehinds invalid in R?](https://stackoverflow.com/questions/13420391/why-is-this-regex-using-lookbehinds-invalid-in-r). In POSIX regex flavors, lookaheads are not supported at all, so one can't use `(?!...)` or `(?=...)` in `sed` or `awk`, or with `grep` unless you use `-P` option. RE2 does not support lookaheads either (so, Go, Google Docs/Sheets REGEX* functions are affected). Oracle regex does not support lookaheads either. – Wiktor Stribiżew Dec 25 '20 at 10:49
  • Just curious if I play around with the demos will they return back to their original state when I leave the site? – Cooper Mar 31 '22 at 23:36
  • Your comment about RE2 was valuable because I just wrote a little thing as a dialog and a webapp and realized when I read your comment that it works because I'm running it client side in javascript. – Cooper Mar 31 '22 at 23:41