Skip to content
Home
Grep Command Guide: Search Like a Pro

Grep Command Guide: Search Like a Pro

Linux Linux 7 min read 1449 words Beginner ExcellentWiki Editorial Team

The grep command is the Swiss Army knife of text searching in Unix-like systems. It searches input files for lines matching a pattern and outputs those lines. Understanding grep thoroughly will make you dramatically more productive on the command line.

Basic Usage

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

# Search multiple files
grep "TODO" *.js

# Read from stdin
ps aux | grep "nginx"

# Case-insensitive search
grep -i "warning" app.log

# Count matches (not lines)
grep -c "error" app.log

# Show line numbers
grep -n "function" script.js

# Invert match (lines NOT containing pattern)
grep -v "debug" app.log

Regular Expressions

Grep supports three regex modes: basic (default), extended (-E), and Perl-compatible (-P).

Basic vs Extended Regex

# Basic (default): +, ?, {, }, (, ), | must be escaped
grep "hello\|world" file.txt    # OR — | must be escaped
grep "colou\?r" file.txt         # ? must be escaped

# Extended (-E): no escaping needed
grep -E "hello|world" file.txt
grep -E "colou?r" file.txt
grep -E "^[A-Z][a-z]{2,}$" names.txt

Practical Regex Examples

# Lines starting with a pattern
grep "^ERROR" /var/log/syslog

# Lines ending with a pattern
grep "\.$" file.txt           # lines ending with period
grep "debug$" app.log         # lines ending with 'debug'

# Email addresses
grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" contacts.txt

# IP addresses
grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" access.log

# Dates in YYYY-MM-DD format
grep -E "\b\d{4}-\d{2}-\d{2}\b" records.txt

# Words with specific characters
grep -E "\bcolou?r\b" file.txt   # matches color or colour

# Empty lines
grep -E "^$" file.txt
grep -c "^$" file.txt            # count empty lines

# Lines with exactly 5 characters
grep -E "^.{5}$" file.txt

Perl-Compatible Regex (-P)

PCRE adds lookaheads, lookbehinds, and non-greedy matching:

# Positive lookahead — match 'foo' only if followed by 'bar'
grep -P "foo(?=bar)" file.txt

# Negative lookahead — match 'foo' only if NOT followed by 'bar'
grep -P "foo(?!bar)" file.txt

# Positive lookbehind — match 'bar' only if preceded by 'foo'
grep -P "(?<=foo)bar" file.txt

# Non-greedy matching
grep -P "<.*?>" file.txt         # matches each tag individually
grep -E "<.*>" file.txt          # matches from first < to last >

Advanced Options

Context Lines

# Show lines before match
grep -B 2 "ERROR" log.txt       # 2 lines before

# Show lines after match
grep -A 3 "ERROR" log.txt       # 3 lines after

# Show lines before and after
grep -C 3 "ERROR" log.txt       # 3 lines each way

Recursive Search

# Search all files in directory
grep -r "TODO" /home/project/

# Search with file pattern (recursive)
grep -r --include="*.js" "async function" .

# Exclude certain files
grep -r --exclude="*.min.js" "console.log" .

# Exclude directories
grep -r --exclude-dir="node_modules" "import" .

# Follow symlinks
grep -R "config" /etc/

# Only show filenames with matches
grep -rl "FIXME" src/

# Only show filenames without matches
grep -rL "FIXME" src/

Binary Files

# Treat binary as text (show matches anyway)
grep -a "pattern" binaryfile

# Skip binary files (default)
grep -I "pattern" directory/    # capital I

# Don't report binary matches
grep --binary-files=without-match "pattern" binaryfile

Output Control

# Only show matching part (not whole line)
grep -o "error" file.txt
grep -oE "\b[A-Z]{2,}\b" file.txt  # extract acronyms

# Colorize matches
grep --color=auto "error" file.txt

# Suppress output, only return exit code
grep -q "pattern" file.txt
echo $?   # 0 if found, 1 if not

# Show matching file names only
grep -l "main" *.c

# Show non-matching file names only
grep -L "main" *.c

# Show only the matched group
grep -oP '"([^"]+)"' file.txt   # extract quoted strings

Performance

# Use fixed strings (much faster than regex)
grep -F "literal.string.with.dots" largefile.txt

# Stop after N matches (early exit)
grep -m 10 "pattern" hugefile.log

# Use LC_ALL for speed with ASCII
LC_ALL=C grep "pattern" hugefile.txt

# Parallel grep with xargs (for multiple files)
find . -name "*.log" | xargs grep "ERROR"

# Use ripgrep for large codebases
rg "pattern" src/                # faster, respects .gitignore

grep vs Alternatives

ToolBest For
grepAvailable everywhere, basic to advanced regex
rg (ripgrep)Fastest, respects .gitignore, UTF-8 aware
ag (the_silver_searcher)Fast code search
ackPer-language awareness, Perl regex
fgrep / grep -FFixed string search (fastest for literals)

Practical Examples

Log Analysis

# Count errors by type
grep -oP 'ERROR \[.*?\]' app.log | sort | uniq -c | sort -rn

# Find IPs making too many requests
grep -oP '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' access.log | sort | uniq -c | sort -rn | head -10

# Extract timestamps between dates
grep "^2024-01-1[5-9]" /var/log/syslog

# Show unique error messages
grep "ERROR" app.log | sort -u

Code Search

# Find TODO/FIXME/HACK comments
grep -rn "\(TODO\|FIXME\|HACK\|XXX\)" src/ --include="*.{js,ts,jsx,tsx}"

# Find function definitions
grep -rn "^def " src/ --include="*.py"

# Find imports from specific module
grep -rn "from 'react'" src/ --include="*.{js,jsx,tsx}"

Real-World Implementation Tips

Production Considerations

When moving from development to production, several factors become critical. Error handling should be comprehensive — every external call (database, API, file system) should have proper error checking, logging, and retry logic where appropriate. Performance monitoring through metrics and structured logging helps identify bottlenecks before they affect users.

Testing Strategy

A thorough testing approach combines multiple levels:

  • Unit tests verify individual functions and methods in isolation
  • Integration tests validate that components work together correctly
  • Edge case tests cover boundary conditions, empty inputs, and error states
  • Performance tests ensure the system meets latency and throughput requirements

Test data should be realistic but controlled. Mock external dependencies to make tests fast and deterministic. Aim for tests that are independent, repeatable, and fast enough to run on every commit.

Documentation

Good documentation is essential for maintainable code. Follow these principles:

  • Document the “why” not just the “what” — explain design decisions
  • Keep examples up to date with the code
  • Include usage examples for public APIs
  • Document configuration options and their defaults
  • Explain error conditions and recovery strategies

Security Best Practices

Security should be considered throughout development:

  • Validate all inputs at system boundaries
  • Use parameterized queries for database access
  • Store secrets in environment variables or secret managers
  • Keep dependencies updated to patch vulnerabilities
  • Apply the principle of least privilege

Performance Optimization

Optimize based on measured data, not assumptions:

  1. Profile before optimizing — identify actual bottlenecks
  2. Measure the impact of each change
  3. Consider the trade-off between speed and readability
  4. Cache expensive operations with appropriate invalidation
  5. Use connection pooling for database and network resources

Monitoring and Observability

Production systems need visibility:

  • Structured logging with correlation IDs for request tracking
  • Metrics for latency, throughput, error rates, and resource usage
  • Health check endpoints for load balancers and orchestration
  • Distributed tracing for request flows across services
  • Alerts for anomaly detection based on baselines

These patterns apply across all programming languages and frameworks. The specific implementation varies, but the principles remain consistent.

FAQ

Q: How do I search for multiple patterns?
A: Use grep -E "pattern1|pattern2" or grep -e "pattern1" -e "pattern2".

Q: How do I search for exact words (not substrings)?
A: Use grep -w "word" — matches only whole words. Equivalent to \bword\b with extended regex.

Q: What is the difference between grep -r and grep -R?
A: grep -r does not follow symlinks. grep -R follows symlinks when traversing directories.

Q: How do I ignore binary files?
A: grep -I skips binary files. grep -a treats binaries as text.

Q: How do I search for patterns with special characters?
A: Use grep -F for fixed strings (no regex interpretation) or escape special characters with \.

Q: Why is grep slow on large files?
A: Use LC_ALL=C grep for ASCII files, grep -F for fixed strings, or switch to ripgrep (rg).

Advanced grep Patterns

Multi-Pattern Search

Grep supports searching for multiple patterns simultaneously:

# Search for either pattern (OR)
grep -E 'error|warning' app.log

# Search for files matching all patterns (AND)
grep -l 'error' *.log | xargs grep -l 'critical'

# Fixed-string search (no regex)
grep -F 'some.literal.string[with].special?chars' data.txt

Context Lines

Control how much surrounding context is displayed:

grep -B 5 'ERROR' app.log   # 5 lines before
grep -A 3 'ERROR' app.log   # 3 lines after
grep -C 2 'ERROR' app.log   # 2 lines before and after

Recursive Search with File Filtering

# Search only Python files
grep -r --include='*.py' 'def ' .

# Exclude node_modules
grep -r --exclude-dir=node_modules 'express' .

# Search files matching a pattern
grep -r --include='*.{js,ts}' 'import' src/

Binary Files and Devices

# Search binary files (shows matches without full content)
grep -a 'pattern' binary-file.bin

# Count matches per file
grep -c 'pattern' *.txt

# Show only the matching part
grep -o '[0-9]\+' data.txt

# Use grep with find for complex file selection
find /var/log -name '*.log' -mtime -7 -exec grep -l 'ERROR' {} \;

For a comprehensive overview, read our article on Bash Scripting Basics.

For a comprehensive overview, read our article on Cron Jobs Guide.

Section: Linux 1449 words 7 min read Beginner 756 articles in section Report inaccuracy Back to top