Download Cheat sheet PDF 12 pages · syntax, editors, patterns, Unicode, performance, debugging
How-to April 26, 2026

Regex match anything except specific characters

The negated character class [^...] is the right tool — clearer than lazy quantifiers, faster than alternation.

The short answer

Use a negated character class — square brackets with a caret at the start:

[^abc]     match any single character except a, b, or c
[^"]       match any character except a double quote
[^\d]      match any non-digit character (same as \D)
[^A-Z]     match anything except uppercase letters

To match multiple characters, add a quantifier: [^"]*, [^abc]+, etc.

How negation works

Inside [...], a caret ^ at the very beginning means "match any character that is NOT one of these." Without the caret, it matches "any character that IS one of these."

[abc]     match a, b, or c
[^abc]    match anything except a, b, c

If the caret isn't the first character, it's literal: [a^b] matches a, ^, or b.

Common use cases

Content between delimiters (the right way)

"[^"]*"        content between double quotes
\[[^\]]*\]    content between square brackets
<[^>]+>        HTML tag with attributes

These are faster and clearer than the lazy alternatives ".*?", \[.*?\], <.+?>.

Words without specific characters

[a-zA-Z]+         only letters
[^aeiouAEIOU]+    only consonants (well, no vowels)
[a-zA-Z][a-zA-Z0-9_]*    identifier (letter then letters/digits/underscores)

Lines not starting with a comment

^[^#]                    line doesn't start with #
^[^#].*                  match the whole line if it doesn't start with #
^(?!#).*$                same idea with negative lookahead

Shorthand negations

Several built-in classes are already negations of common groups:

Shorthand Equivalent Meaning
\D[^0-9]non-digit
\W[^A-Za-z0-9_]non-word
\S[^\s]non-whitespace

Excluding multiple things

Combine literal characters, ranges, and shorthand classes inside the negation:

[^\d\s.,!?]      not a digit, whitespace, or punctuation
[^a-zA-Z0-9]      not alphanumeric
[^"']            not a quote (either kind)
[^<>]             not an angle bracket

Excluding newlines

. already excludes newlines by default. So . and [^\n] are similar — but watch the differences:

.            any char except \n (and \r in some flavors)
[^\n]        any char except \n only

For most use cases . is fine. Use [^\n] when you specifically want to allow \r (Windows line endings) but not \n.

Negative lookarounds for "not preceded by"

Character classes negate one character at a time. For "not preceded by X" or "not followed by X", use lookarounds:

(?<!@)word        match "word" if NOT preceded by @
word(?!ing)       match "word" if NOT followed by "ing"

Combining negation with other constraints

You can negate one class and intersect with another using lookarounds:

(?=[^aeiou])[a-z]     a lowercase letter that's not a vowel

Or, in flavors with class intersection (Java, ES2024 with /v flag):

[a-z&&[^aeiou]]      lowercase consonants (Java)
[[a-z]--[aeiou]]    same idea (ES2024 /v)

Common mistakes

Putting the caret in the wrong place

[a^bc]    matches a, ^, b, or c — caret is literal!
[^abc]    matches anything except a, b, c

The negation caret MUST be the first character inside the brackets.

Forgetting that ] needs escaping

Inside [...], a literal ] usually needs escaping (or being the first character right after the opening bracket / caret):

[]a-z]     matches ] or lowercase letter — ] as first char is literal
[\]a-z]    safer — escape it explicitly

The takeaway

The negated character class [^...] is one of the most useful constructs in regex. Use it for:

  • Content between delimiters (much cleaner than lazy)
  • "Anything except this single character or set"
  • Excluding specific characters from a broader pattern

For "not preceded by" or "not followed by" — patterns about position rather than a single character — use negative lookarounds instead.


Related reading


Try this pattern in the explainer

Paste any regex into the live explainer and see what each token means, with example matches in real time.

Open the regex explainer →