skip to content

grep β€” Pattern Search

Search files and streams using fixed strings, extended regex, or PCRE. Covers all major flags, context, recursive search, and pipeline patterns.

4 min read 10 snippets 2d ago intermediate

grep β€” Pattern Search#

Syntax#

grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] -e PATTERN -e PATTERN [FILE...]
grep [OPTIONS] -f PATTERNFILE [FILE...]

Essential flags#

FlagMeaning
-iCase-insensitive match
-vInvert match (non-matching lines)
-nShow line numbers
-cPrint match count per file
-lPrint only filenames with matches
-LPrint only filenames with no match
-r / -RRecursive (follow symlinks with -R)
-wMatch whole word only
-xMatch whole line only
-oPrint only the matching part of the line
-qQuiet β€” exit 0 if match found, no output
-sSuppress error messages about missing files
-m NStop after N matches
-hSuppress filename prefix (multi-file mode)
-HAlways print filename prefix

Regex flavours#

FlagEngineNotes
grepBRE (basic)\+ | \( \) need backslash
grep -E / egrepERE (extended)+ | () unescaped
grep -PPCRE\d \w (?=...) lookaheads etc.
grep -F / fgrepFixed stringNo regex, fastest for literals

Context lines#

grep -A 3 "ERROR" app.log      # 3 lines After match
grep -B 2 "ERROR" app.log      # 2 lines Before match
grep -C 5 "ERROR" app.log      # 5 lines before and after (Context)

Character classes & anchors#

grep '^root'         /etc/passwd   # lines starting with "root"
grep 'bash$'         /etc/passwd   # lines ending with "bash"
grep '^$'            file.txt      # empty lines
grep -E '[0-9]{4}'   data.txt      # exactly 4 digits
grep -P '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' ips.txt  # IPv4 addresses

Multiple patterns#

grep -e "error" -e "warn" -e "crit" /var/log/syslog

# Or from a file (one pattern per line)
grep -f patterns.txt logfile
grep -r "TODO" ./src/
grep -rl "console.log" ./src/           # filenames only
grep -rn --include="*.py" "import" .    # only .py files
grep -r --exclude="*.min.js" "fetch" .  # skip minified files
grep -r --exclude-dir={.git,node_modules,dist} "pattern" .

Colour and output control#

grep --color=always "error" log | less -R   # keep colour through pipe
grep -o '"[^"]*"' file.json                 # extract all quoted strings
grep -oP '(?<=href=")[^"]*' page.html       # PCRE lookbehind β€” all href values
grep -n "" file.txt                          # number every line (cat -n alternative)

Count and statistics#

grep -c "ERROR" app.log                 # match count in one file
grep -rc "TODO" src/ | sort -t: -k2 -rn  # per-file TODO counts, sorted

# Number of unique matching lines
grep "pattern" file | sort -u | wc -l

Exit codes#

CodeMeaning
0At least one match found
1No match found
2Error (bad option, missing file)
# Use in conditionals
if grep -q "FAILED" build.log; then
  echo "Build had failures"
fi

# Check without output
grep -qs "pattern" file && echo "found"

Binary files#

grep -a "pattern" binary.bin    # treat binary as text
grep -I "pattern" *             # skip binary files silently
grep --binary-files=text "str" img.bin

Practical pipelines#

# Find processes by name
ps aux | grep -v grep | grep nginx

# Extract unique IPs from access log
grep -oP '\d+\.\d+\.\d+\.\d+' access.log | sort -u

# Show lines between two patterns (inclusive)
grep -A 9999 "START" file | grep -B 9999 "END"

# Find files containing all of two patterns
grep -rl "alpha" . | xargs grep -l "beta"

# Lines that DON'T contain either of two words
grep -v -e "debug" -e "trace" app.log

# Highlight matches but show all lines
grep --color=always -E "error|$" app.log

Tips#

[!TIP] Use grep -F for literal string searches (no regex overhead) β€” significantly faster on large files when you don’t need pattern matching.

[!TIP] grep -P (PCRE) is not available on BSD/macOS by default. Use ggrep -P (via Homebrew grep) or switch to ripgrep which has PCRE2 built-in.