Regex
Programming
Coding
Syntax
Tutorial

How to negate specific word in regex?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

To match lines that do NOT contain a specific word, use a negative lookahead: ^(?!.*\bword\b).*$. This pattern asserts at the start of the line that the word does not appear anywhere, then matches the entire line. This works in most modern regex engines including Python, JavaScript, Java, .NET, and PCRE.

How Negative Lookahead Works

A negative lookahead (?!pattern) checks that the specified pattern does NOT match at the current position, without consuming any characters. It is a zero-width assertion, meaning it looks ahead but does not advance the regex cursor.

Breaking down ^(?!.*\bword\b).*$:

  • ^ anchors to the start of the line
  • (?!.*\bword\b) asserts that from this position, there is no way to match any characters followed by "word" as a complete word
  • .*$ matches the entire line (only reached if the lookahead passes)

The \b word boundaries ensure you match the complete word "word" and not substrings like "wordy" or "sword".

Practical Examples by Language

Python

python
1import re
2
3lines = [
4    "The quick brown fox",
5    "The lazy dog",
6    "The fox jumped over the dog",
7    "No animals here"
8]
9
10# Match lines that do NOT contain "fox"
11pattern = re.compile(r"^(?!.*\bfox\b).*$", re.MULTILINE)
12
13for line in lines:
14    if pattern.match(line):
15        print(f"Matched: {line}")
16
17# Output:
18# Matched: The lazy dog
19# Matched: No animals here

JavaScript

javascript
1const lines = [
2  "The quick brown fox",
3  "The lazy dog",
4  "The fox jumped over the dog",
5  "No animals here"
6];
7
8const pattern = /^(?!.*\bfox\b).*$/;
9
10lines.filter(line => pattern.test(line))
11     .forEach(line => console.log(`Matched: ${line}`));
12
13// Output:
14// Matched: The lazy dog
15// Matched: No animals here

Java

java
1import java.util.regex.Pattern;
2import java.util.regex.Matcher;
3
4String[] lines = {
5    "The quick brown fox",
6    "The lazy dog",
7    "The fox jumped over the dog",
8    "No animals here"
9};
10
11Pattern pattern = Pattern.compile("^(?!.*\\bfox\\b).*$");
12
13for (String line : lines) {
14    if (pattern.matcher(line).matches()) {
15        System.out.println("Matched: " + line);
16    }
17}

grep (Command Line)

bash
1# Using grep -P (PCRE) for lookahead support
2grep -P "^(?!.*\bfox\b).*$" file.txt
3
4# Simpler alternative: grep -v for inverse matching
5grep -v "\bfox\b" file.txt

The grep -v approach is simpler and often more readable when you just need to filter lines in a file.

Negating Multiple Words

To exclude lines containing ANY of several words, chain the lookaheads:

python
1import re
2
3# Exclude lines containing "error" OR "warning" OR "fatal"
4pattern = re.compile(
5    r"^(?!.*\berror\b)(?!.*\bwarning\b)(?!.*\bfatal\b).*$",
6    re.MULTILINE | re.IGNORECASE
7)
8
9log_lines = [
10    "INFO: Server started on port 8080",
11    "ERROR: Connection refused",
12    "WARNING: Disk space low",
13    "INFO: Request processed in 42ms",
14    "FATAL: Out of memory"
15]
16
17for line in log_lines:
18    if pattern.match(line):
19        print(line)
20
21# Output:
22# INFO: Server started on port 8080
23# INFO: Request processed in 42ms

To exclude lines containing ALL of several words (the line must contain every word to be excluded):

python
1# Exclude only lines containing BOTH "error" AND "database"
2pattern = re.compile(
3    r"^(?!(?=.*\berror\b)(?=.*\bdatabase\b)).*$",
4    re.MULTILINE | re.IGNORECASE
5)

Negating a Word at a Specific Position

Sometimes you do not want to exclude the entire line. You want to match a word that is NOT a specific value at a certain position:

python
1import re
2
3# Match any word after "color:" that is NOT "red"
4text = "color: blue, color: red, color: green"
5matches = re.findall(r"color:\s+(?!red\b)(\w+)", text)
6print(matches)  # ['blue', 'green']

Matching Words That Do Not Start With a Prefix

python
1import re
2
3words = ["unhappy", "undo", "happy", "united", "done"]
4
5# Match words that do NOT start with "un"
6pattern = re.compile(r"\b(?!un)\w+\b")
7matches = pattern.findall(" ".join(words))
8print(matches)  # ['happy', 'done']

Technique Comparison

TechniquePatternUse CaseEngine Support
Negative lookahead (full line)^(?!.*\bword\b).*$Exclude lines containing a wordPython, JS, Java, .NET, PCRE
Negative lookahead (position)(?!word\b)\w+Match any word except a specific onePython, JS, Java, .NET, PCRE
grep inversegrep -v "\bword\b"Filter lines in filesAll grep implementations
Character class negation[^abc]Exclude specific characters (NOT words)All engines
Negative lookbehind(?<!prefix)\w+Match words not preceded by a patternPython, Java, .NET (fixed-width)
Tempered greedy token(?:(?!\bword\b).)* Match text between boundaries, skipping a wordPython, Java, .NET, PCRE

Character Class Negation vs. Word Negation

A common misconception is that [^word] negates the word "word." It does not. Character class negation [^...] only negates individual characters:

python
1import re
2
3# [^abc] matches any single character that is NOT a, b, or c
4re.findall(r"[^abc]", "abcdef")  # ['d', 'e', 'f']
5
6# [^word] matches any single character that is NOT w, o, r, or d
7re.findall(r"[^word]", "hello world")  # ['h', 'e', 'l', 'l', ' ', 'l']
8
9# To negate the WORD "word", use a negative lookahead
10re.findall(r"\b(?!word\b)\w+", "this word is good")  # ['this', 'is', 'good']

Performance Considerations

Negative lookaheads add computational cost because the regex engine must attempt to match the negated pattern at each position. For large texts, consider these optimizations:

python
1# Slower: lookahead scans the entire remaining line at each position
2pattern = re.compile(r"^(?!.*\bfox\b).*$", re.MULTILINE)
3
4# Faster for simple cases: use Python's string methods instead
5result = [line for line in text.splitlines() if "fox" not in line]
6
7# Fastest for file filtering: use grep -v
8# grep -v "\bfox\b" file.txt

For programmatic use where you need regex for complex pattern matching, the lookahead approach is fine for typical text sizes. For processing millions of lines, plain string methods or specialized tools like grep will outperform regex lookaheads.

Common Pitfalls

Forgetting word boundaries. Without \b, the pattern (?!.*error) also matches against substrings. The word "terrorism" contains "error"? No, but "errorless" contains "error". Using \b on both sides ensures you match whole words only.

Confusing character class negation with word negation. [^fox] does not mean "not the word fox." It means "any character that is not f, o, or x." Always use negative lookahead for word-level negation.

Missing anchors. Without ^ and $, the regex (?!.*\bfox\b).* can match partial lines, producing unexpected results. Always anchor to the line boundaries when filtering entire lines.

Case sensitivity. The pattern \bfox\b does not match "Fox" or "FOX." Add the case-insensitive flag (re.IGNORECASE in Python, /i in JavaScript) if needed.

Using negation in engines without lookahead support. Older or simpler regex engines (like POSIX BRE used in basic grep or sed without -E) do not support lookaheads. Use grep -v or grep -P (PCRE mode) as alternatives.

Over-engineering with regex. If you just need to check whether a string contains a word, a simple if "word" not in text (Python) or !text.includes("word") (JavaScript) is clearer and faster than regex.

Summary

Use ^(?!.*\bword\b).*$ with a negative lookahead to match lines that do not contain a specific word. Use \b word boundaries to avoid partial matches. Chain multiple lookaheads to exclude multiple words. For simple line filtering in files, grep -v is often a better tool than regex. Remember that [^...] negates characters, not words. For performance-sensitive applications processing large volumes of text, consider plain string methods before reaching for regex lookaheads.


Course illustration
Course illustration

All Rights Reserved.