138

I have a regex, for example (ma|(t){1}). It matches ma and t and doesn't match bla.

I want to negate the regex, thus it must match bla and not ma and t, by adding something to this regex. I know I can write bla, the actual regex is however more complex.

Griffin
  • 2,399
  • 7
  • 48
  • 83
IAdapter
  • 62,595
  • 73
  • 179
  • 242

5 Answers5

131

Use negative lookaround: (?!pattern)

Positive lookarounds can be used to assert that a pattern matches. Negative lookarounds is the opposite: it's used to assert that a pattern DOES NOT match. Some flavor supports assertions; some puts limitations on lookbehind, etc.

Links to regular-expressions.info

See also

More examples

These are attempts to come up with regex solutions to toy problems as exercises; they should be educational if you're trying to learn the various ways you can use lookarounds (nesting them, using them to capture, etc):

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
65

Assuming you only want to disallow strings that match the regex completely (i.e., mmbla is okay, but mm isn't), this is what you want:

^(?!(?:m{2}|t)$).*$

(?!(?:m{2}|t)$) is a negative lookahead; it says "starting from the current position, the next few characters are not mm or t, followed by the end of the string." The start anchor (^) at the beginning ensures that the lookahead is applied at the beginning of the string. If that succeeds, the .* goes ahead and consumes the string.

FYI, if you're using Java's matches() method, you don't really need the the ^ and the final $, but they don't do any harm. The $ inside the lookahead is required, though.

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
  • 3
    Most helpful part of this answer is that you have to add `.*` to the end of your regex, otherwise it will reject every string. – Rav Mar 21 '18 at 13:08
  • 2
    The `$` *inside* the negative lookahead, AND the `.*` at the end are both critical bits. As always with REs, a strong set of unit tests is absolutely critical to getting it right. This answer is 100% correct. – Tom Dibble Aug 07 '18 at 19:30
2
\b(?=\w)(?!(ma|(t){1}))\b(\w*)

this is for the given regex.
the \b is to find word boundary.
the positive look ahead (?=\w) is here to avoid spaces.
the negative look ahead over the original regex is to prevent matches of it.
and finally the (\w*) is to catch all the words that are left.
the group that will hold the words is group 3.
the simple (?!pattern) will not work as any sub-string will match
the simple ^(?!(?:m{2}|t)$).*$ will not work as it's granularity is full lines

Ofer Skulsky
  • 685
  • 4
  • 10
-1

This regexp math your condition:

^.*(?<!ma|t)$

Look at how it works: https://regex101.com/r/Ryg2FX/1

Podrepny
  • 29
  • 3
-2

Apply this if you use laravel.

Laravel has a not_regex where field under validation must not match the given regular expression; uses the PHP preg_match function internally.

'email' => 'not_regex:/^.+$/i'
DAVID AJAYI
  • 1,912
  • 20
  • 13