Toolmingo
Guides8 min read

grep Cheat Sheet: Every Option You Actually Need

A complete grep cheat sheet — basic patterns, regex, case-insensitive search, recursive search, context lines, output control, and real-world examples. Copy-ready grep commands.

grep (Global Regular Expression Print) searches files for lines matching a pattern. It's one of the most-used Unix commands — for log analysis, code search, and pipeline filtering.

Quick reference

Flag What it does
-i Case-insensitive match
-r / -R Recursive search in directory
-l Print only filenames with matches
-L Print filenames with no matches
-n Show line numbers
-c Count matching lines per file
-v Invert match (lines that don't match)
-w Whole word match
-x Whole line match
-E Extended regex (same as egrep)
-P Perl-compatible regex (PCRE)
-F Fixed string, no regex (same as fgrep)
-o Print only the matching part
-A N N lines after match
-B N N lines before match
-C N N lines before and after (context)
-m N Stop after N matches
-q Quiet — exit 0 if match found, no output
--include=GLOB Only search matching filenames
--exclude=GLOB Skip matching filenames
--exclude-dir=DIR Skip directory
-H Always print filename (default for -r)
-h Never print filename
--color Highlight match in output
-s Suppress error messages

Basic usage

# Search for a pattern in a file
grep "error" /var/log/syslog

# Search in multiple files
grep "TODO" src/index.ts src/utils.ts

# Case-insensitive
grep -i "error" /var/log/syslog

# Show line numbers
grep -n "error" /var/log/syslog

# Count matches
grep -c "error" /var/log/syslog

# Invert: lines without the pattern
grep -v "DEBUG" app.log

Recursive directory search

# Search all files in directory
grep -r "TODO" ./src

# Also follow symlinks
grep -R "TODO" ./src

# Show only filenames (not content)
grep -rl "TODO" ./src

# Search specific file types
grep -r "useState" ./src --include="*.tsx"
grep -r "console.log" ./src --include="*.{js,ts}"

# Exclude files
grep -r "password" . --exclude="*.lock" --exclude-dir=node_modules

# Common: skip generated dirs
grep -r "apiUrl" . \
  --include="*.ts" \
  --exclude-dir=node_modules \
  --exclude-dir=.git \
  --exclude-dir=dist

Regex patterns

grep supports POSIX basic regex by default. Use -E for extended regex (alternation, +, ?) or -P for Perl regex (lookahead, \d, \w).

# Basic regex (BRE)
grep "error[0-9]" app.log        # char class
grep "^Error" app.log             # start of line
grep "\.js$" file.txt             # end of line
grep "col.ur" file.txt            # any char (. = wildcard)

# Extended regex (-E or egrep)
grep -E "error|warning" app.log   # alternation
grep -E "colou?r" file.txt        # optional u
grep -E "go{2,}" file.txt         # 2+ o's (goo, gooo…)
grep -E "https?://" urls.txt      # http or https

# Perl-compatible regex (-P)
grep -P "\d{3}-\d{4}" contacts.txt    # phone numbers
grep -P "^\s*$" file.txt               # blank/whitespace-only lines
grep -P "(?<=Bearer )\S+" log.txt      # lookbehind (tokens)
grep -P "\b(foo|bar)\b" file.txt       # word boundary alternation

Character classes

# POSIX classes
grep "[[:alpha:]]" file.txt       # any letter
grep "[[:digit:]]" file.txt       # any digit (0-9)
grep "[[:alnum:]]" file.txt       # letter or digit
grep "[[:space:]]" file.txt       # whitespace
grep "[[:upper:]]" file.txt       # uppercase letter
grep "[[:lower:]]" file.txt       # lowercase letter
grep "[[:punct:]]" file.txt       # punctuation

# Ranges
grep "[a-z]" file.txt
grep "[A-Z0-9]" file.txt
grep "[^0-9]" file.txt            # NOT a digit

Context lines

# 3 lines after the match
grep -A 3 "Exception" app.log

# 3 lines before
grep -B 3 "Exception" app.log

# 3 lines before and after
grep -C 3 "Exception" app.log

# Useful: find a function definition + body
grep -A 20 "^function processPayment" src/payments.js

Output control

# Only print matching part (not whole line)
grep -o "https\?://[^ ]*" file.txt

# Stop after first 5 matches
grep -m 5 "error" app.log

# Quiet mode — useful in scripts
if grep -q "error" app.log; then
  echo "Errors found"
fi

# Colorize output
grep --color=auto "error" app.log
# Add to ~/.bashrc:
alias grep='grep --color=auto'

# Null-separated output (safe for filenames with spaces)
grep -rlZ "TODO" . | xargs -0 wc -l

Fixed string search (no regex)

# -F treats pattern as literal string, not regex
grep -F "user.name" file.txt      # finds "user.name" not "userXname"
grep -F "$HOME" script.sh         # finds literal "$HOME"
grep -F "^D" data.txt             # literal "^D", not start-of-line

Multiple patterns

# Match either pattern (-E with |)
grep -E "error|warning|fatal" app.log

# Match multiple fixed strings (-F with |)
grep -F -e "error" -e "warning" -e "fatal" app.log

# From a file of patterns (one per line)
cat patterns.txt
# error
# warning
# fatal
grep -f patterns.txt app.log

# AND logic: pipe two greps
grep "error" app.log | grep "database"

Whole word and whole line

# Whole word: won't match "errors" or "prerror"
grep -w "error" app.log

# Whole line: entire line must match exactly
grep -x "404 Not Found" status.log

# Combine: case-insensitive whole word
grep -iw "todo" src/main.ts

File listing flags

# Files that HAVE matches
grep -rl "TODO" ./src

# Files that DON'T have matches (no TODO)
grep -rL "TODO" ./src

# Show filename always (even single file)
grep -H "error" app.log

# Never show filename
grep -rh "TODO" ./src

Practical patterns

Find all TODO/FIXME in codebase

grep -rn "TODO\|FIXME\|HACK\|XXX" . \
  --include="*.ts" \
  --exclude-dir=node_modules \
  --exclude-dir=.git

Search Git-tracked files only

git grep "console.log"
git grep -n "TODO"
git grep -l "password"

Find large or complex functions (heuristic)

# Functions with many lines — find starts
grep -n "^function \|^  function " src/*.js

# Find all exported functions
grep -rn "^export function\|^export const" src/

Log analysis

# Errors in last hour (if logs have timestamps)
grep "$(date -d '1 hour ago' '+%Y-%m-%d %H')" app.log | grep -i "error"

# Count errors by type
grep -oE "(ERROR|WARN|INFO)" app.log | sort | uniq -c | sort -rn

# Unique IPs from access log
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" access.log | sort -u

# Find slow requests (> 1000ms)
grep -E "ms=[0-9]{4,}" access.log

Validate config / find missing values

# Find empty values in .env style files
grep -E "^\w+=\s*$" .env.example

# Find hard-coded API keys (rough heuristic)
grep -rE "api[_-]?key\s*=\s*['\"][a-zA-Z0-9]{20,}" . \
  --exclude-dir=node_modules

# Find debug flags left on
grep -rn "debug\s*=\s*true\|DEBUG\s*=\s*1" . --include="*.{json,yaml,yml,env}"

Code review helpers

# All console.log left in code
grep -rn "console\.\(log\|warn\|error\|debug\)" src/ --include="*.ts"

# Hard-coded localhost URLs
grep -rn "localhost:[0-9]\+" src/ --include="*.{ts,tsx,js}"

# Missing error handling (async functions without try/catch)
grep -n "async " src/api/*.ts | grep -v "try\|catch"

Pipeline integration

# With xargs
grep -rl "oldFunction" src/ | xargs sed -i 's/oldFunction/newFunction/g'

# With awk for field extraction
grep "POST /api" access.log | awk '{print $7}' | sort | uniq -c | sort -rn

# With sort and uniq
grep -h "Error:" *.log | sort | uniq -c | sort -rn | head -20

# Highlight matches in less
grep -E "error|$" app.log | less -R

# Count non-empty lines
grep -c "." file.txt

Exit codes

grep exits with a code that scripts can check:

Exit code Meaning
0 Match found
1 No match
2 Error (file not found, bad regex, etc.)
# In shell scripts
grep -q "error" app.log && echo "Found errors!" || echo "No errors"

# In CI: fail if debug code left in
grep -rq "console.log" src/ && { echo "Remove console.log before commit"; exit 1; }

grep vs ripgrep (rg)

ripgrep (rg) is a faster alternative that respects .gitignore by default.

Task grep ripgrep
Basic search grep -r "pat" . rg "pat"
Case-insensitive grep -ri "pat" . rg -i "pat"
File type filter --include="*.ts" -t ts
Respect .gitignore manual --exclude-dir automatic
Speed baseline 5–10× faster
PCRE -P -P
Fixed string -F -F

Use grep when it's already available (scripts, containers). Use rg for daily interactive use.

Common mistakes

Mistake Problem Fix
grep "user.name" file . matches any char, finds "userXname" grep -F "user.name" or grep "user\.name"
grep "error|warning" with BRE | is BRE alternation — not all systems support it grep -E "error|warning"
grep -r pattern dir/ without exclude Searches node_modules, .git, etc. Add --exclude-dir=node_modules --exclude-dir=.git
grep "^" to count lines Matches blank lines too Use wc -l or grep -c "." for non-empty
Forgetting -P for \d, \w BRE/ERE don't support \d Use -P or [0-9] / [a-zA-Z0-9_]
grep -l then editing in place -l gives filenames, but xargs grep re-reads Use xargs sed -i after grep -rl
Unquoted pattern with spaces Shell splits the pattern Always quote: grep "two words" file

6 FAQ

Q: How do I search for a string that starts with a dash (-)?
Use -- to end options: grep -- "-v" file.txt, or use \-: grep "\-v" file.txt.

Q: How do I search for a newline inside grep?
grep works line by line — it can't match across lines. Use pcregrep -M or awk for multi-line patterns.

Q: What's the difference between -E, -P, and basic grep?
Basic regex (BRE): grep. Extended regex — adds +, ?, |, {} without backslash: grep -E or egrep. Perl regex — adds \d, \w, lookahead/behind: grep -P. Use -E for most cases; -P for advanced patterns.

Q: How do I grep for a tab character?
grep $'\t' file.txt (using ANSI-C quoting in bash), or grep -P "\t" file.txt.

Q: Why does grep -r miss some files?
It skips binary files by default. Use -a to treat binary as text. Also check --include/--exclude filters.

Q: How do I make grep output machine-readable?
Use -o for only the match, -h to suppress filenames, -Z for null-separated filenames (safe for xargs -0), and --no-messages to silence errors.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools