grep
grep (Global Regular Expression Print) searches files or stdin for lines matching a pattern and prints matching lines. It is the standard tool for filtering log files, searching code, and extracting information from command output in Linux environments.
Understanding grep
What Is grep in Simple Terms
grep reads input line by line and prints only the lines that match a pattern. The pattern can be a simple string or a regular expression. It is the first tool to reach for when you need to find something in a log file, config file, or command output.
grep 'ERROR' /var/log/app.log — prints every line containing ERROR. Simple, fast, and handles files of any size.
+------------------------------------------+| Input: /var/log/app.log (1000 lines) |+------------------------------------------+ | v+------------------------------------------+| grep -E 'ERROR|FATAL' -n -A 2 || Reads line by line || Evaluates regex against each line |+------------------------------------------+ | match found | v+------------------------------------------+| Output: matching lines + line numbers || 42:2024-01-15 ERROR Connection failed || 43: at payment.js:123 |+------------------------------------------+Practical Commands
## Basic pattern searchgrep 'ERROR' /var/log/app.log ## Case-insensitive searchgrep -i 'error' /var/log/app.log ## Invert match (lines NOT containing pattern)grep -v 'DEBUG' /var/log/app.log ## Show line numbersgrep -n 'ERROR' /var/log/app.log ## Count matching linesgrep -c 'ERROR' /var/log/app.log ## Show filenames only (useful with multiple files)grep -l 'ERROR' /var/log/*.log ## Recursive search through directoriesgrep -r 'database_url' /etc/grep -r 'API_KEY' /opt/apps/ --include='*.py' ## Show context: 3 lines before and after matchgrep -B 3 -A 3 'CRITICAL' /var/log/app.log ## Extended regex (alternation, +, ?)grep -E 'ERROR|FATAL|CRITICAL' /var/log/app.loggrep -E 'error[0-9]+' /var/log/app.log ## Perl regex (lookahead, lookbehind)grep -P '(?<=user_id=)\d+' /var/log/app.log ## Quiet mode (exit code only, no output)if grep -q 'FATAL' /var/log/app.log; then echo "Fatal errors found!"fi ## Search compressed fileszgrep 'ERROR' /var/log/app.log.gz ## Common production log analysis patterns: ## Count errors by hourgrep 'ERROR' /var/log/app.log | awk '{print $1, $2}' | cut -c1-13 | sort | uniq -c ## Find IPs with most failed loginsgrep 'Failed password' /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -10 ## Extract all unique error messagesgrep 'ERROR' /var/log/app.log | sed 's/.*ERROR: //' | sort | uniq -c | sort -rnTroubleshooting
| Symptom | Command | What to Check |
|---|---|---|
| Pattern not matching | `echo 'test' | grep 'pattern'` |
| Too many results | Add -v or more specific pattern |
Filter out unwanted lines |
| Binary file skipped | grep -a or `strings file |
grep` |
Tip
grep -E(extended regex) is almost always better than basicgrepfor production log analysis. It supports|for alternation,+for one-or-more, and?for optional — without needing to escape them. Usegrep -E 'ERROR|WARN|FATAL'instead ofgrep 'ERROR\|WARN\|FATAL'.
Remember
grepexit code 0 means matches found, exit code 1 means no matches, exit code 2 means an error occurred. This makesgrep -q pattern fileperfect for conditionals in scripts — it exits immediately on first match without printing anything.
Frequently Asked Questions
What's the difference between grep, egrep, and grep -P that actually affects how you write patterns?
Plain grep uses Basic Regular Expressions (BRE), where metacharacters like `+`, `?`, and `|` must be escaped (`\+`) to have special meaning. `egrep` (or `grep -E`) uses Extended Regular Expressions (ERE), where those characters work unescaped. `grep -P` enables PCRE (Perl-compatible regex), adding lookaheads/lookbehinds and non-greedy quantifiers that neither BRE nor ERE support — necessary for patterns like matching text NOT followed by a certain string.
What's a common grep mistake when searching logs at scale?
Using grep without `-F` on a pattern that's actually a literal string containing regex special characters (like an IP address with dots, or a URL) — the dots match any character, not just literal periods, occasionally producing false-positive matches on large log files. For pure literal-string search, `grep -F` (fixed-string mode) is both more correct and noticeably faster than treating a literal as a regex, since it skips the regex engine entirely.