Skip to content

/commands/grep/grep-invert-match

grep -v: exclude lines that match a pattern (invert match)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · grep (GNU grep) 3.0updated
tool
grep
versions
GNU grep 3.x
os
linux, macos, windows

grep -v pattern file prints every line that does not match the pattern, so it removes lines from the output. Typical uses: grep -v DEBUG app.log hides debug messages, grep -v '^#' config drops comment lines, and ps aux | grep nginx | grep -v grep hides the grep process itself. Combine it with -e or -E to exclude several patterns at once.

Example

bash
cat > app.conf <<'EOF'
# main settings
port = 8080

# logging
level = info
  # indented comment
name = demo
EOF
grep -v '^#' app.conf
echo ===
grep -Ev '^[[:space:]]*(#|$)' app.conf
echo ===
grep -vc '^#' app.conf

Output

port = 8080

level = info
  # indented comment
name = demo
===
port = 8080
level = info
name = demo
===
5

The first command removes lines that start with # but keeps the empty lines and the indented comment. The second uses one extended regex for lines that are empty or start with optional blanks and #, and prints only the settings. -vc counts the lines that do not match.

Common forms

CommandKeeps
grep -v DEBUG fLines without DEBUG
grep -v -e DEBUG -e TRACE fLines with neither DEBUG nor TRACE
grep -Ev 'DEBUG|TRACE' fSame, with an extended regex
grep -v '^$' fNon-empty lines
grep -Ev '^[[:space:]]*(#|$)' fLines that are not comments or blank
grep -vi warning fLines without warning in any case
grep -vw id fLines without the whole word id (keeps lines with valid or ids)
grep -vF -f stop.txt fLines containing none of the fixed strings listed in stop.txt
grep ERROR f | grep -v timeoutERROR lines except timeouts

Remove the lines of one file from another

bash
printf '%s\n' ada bob cyd dan > all.txt
printf '%s\n' bob dan > done.txt
grep -vxF -f done.txt all.txt

Output

ada
cyd

-f done.txt reads the patterns from a file, -F treats them as fixed strings and -x makes each pattern match a whole line, so bob does not also remove bobby. The result is the lines of all.txt that are not in done.txt.

Pitfalls

  • An empty pattern file excludes nothing: grep -v -f empty.txt prints every line, because no pattern can match.
  • Windows line endings: a pattern file saved with CRLF endings has a \r at the end of each pattern, so -x never matches. Convert it with tr -d '\r' first.
  • Exit status: grep -v exits 0 when it printed at least one line and 1 when every line matched, which can stop scripts that use set -e.
  • -v with -o prints nothing, because there is no matching part to show in a line that does not match.

For deleting lines in place rather than filtering output, sed -i '/pattern/d' file does the same selection and rewrites the file.

FAQ

How do I exclude several patterns at once?

Give every pattern with -e, as in grep -v -e DEBUG -e TRACE file, or use one extended regex, grep -Ev 'DEBUG|TRACE' file. A line is printed only if it matches none of them.

Why does grep -v exit with status 1 when it printed nothing?

The exit status reports whether any line was selected. With -v the selected lines are the ones that do not match, so status 1 means every input line matched the pattern. In scripts with set -e, add || true where an empty result is acceptable.

How do I exclude files, not lines?

Use -L to list files that contain no match, or --exclude and --exclude-dir to skip files during a recursive search. -v works on lines inside each file.

Sources