| Tested on | Ubuntu 25.04 (Plucky Puffin) |
|---|---|
| Package | grep (GNU) 3.11 |
| Applies to | Ubuntu, Debian, RHEL, Fedora, SUSE macOS |
| Privilege | sudo or root |
| Man page | grep(1) |
| Scope | Match lines with extended and Perl regex, pattern files, whole words, and context lines on files or stdin. This page covers pattern engines and line-level matching — not recursive directory walks. |
| Related guides | grep exact match examples Linux commands |
grep — quick reference
Pattern engines
Choose how grep interprets the search text.
| When to use | Command |
|---|---|
| Default basic regex on a single file | grep 'error' app.log |
Extended regex — alternation, groups, +, ? |
grep -E 'error|warning' app.log |
Perl regex — lookaheads, \d, non-greedy groups |
grep -P '(?=.*error)(?=.*db)' app.log |
| Fixed string — dots and brackets are literal | grep -F 'rate.limit' app.log |
| Multiple patterns in one command | grep -e error -e warning app.log |
| Many patterns listed in a file | grep -f patterns.txt app.log |
Whole word and whole line
Tighten matches when substrings or partial lines are noise.
| When to use | Command |
|---|---|
| Match a whole word only | grep -w log words.txt |
| Match only when the entire line equals the pattern | grep -x 'exact line' file.txt |
| Case-insensitive pattern | grep -i error app.log |
Context and extraction
See surrounding log lines or pull out just the matching part.
| When to use | Command |
|---|---|
| Lines after each match | grep -A 2 error app.log |
| Lines before each match | grep -B 2 error app.log |
| Lines before and after | grep -C 2 error app.log |
| Print only the matched text, not the full line | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' access.log |
| Invert — lines that do not match | grep -v debug app.log |
Character classes and anchors
Common building blocks for basic and extended regex on one file or stdin.
| When to use | Command |
|---|---|
| Lines containing any digit | grep '[0-9]' file.txt |
| Lines starting with a prefix | grep '^Error' app.log |
| Lines ending with a suffix | grep 'failed$' app.log |
| Alternation without extra backslashes | grep -E 'failed|denied|invalid' auth.log |
grep — command syntax
Synopsis from grep --help on Ubuntu 25.04 (GNU grep 3.11):
Usage: grep [OPTION]... PATTERNS [FILE]...
Search for PATTERNS in each FILE.
-E, --extended-regexp PATTERNS are extended regular expressions
-F, --fixed-strings PATTERNS are strings
-P, --perl-regexp PATTERNS are Perl regular expressions
-e, --regexp=PATTERNS use PATTERNS for matching
-f, --file=FILE take PATTERNS from FILE
-w, --word-regexp match only whole words
-x, --line-regexp match only whole lines
-A, -B, -C NUM context lines after / before / around match
-o, --only-matching show only nonempty parts of lines that matchWith no FILE, grep reads standard input — the usual pattern in pipelines. To search entire directory trees, see grep recursive search.
grep — command examples
Essential Search one file or piped stdin
Pattern matching starts on a single stream: one file or text piped from another command.
Create a sample log and search it:
cat > /tmp/sample.log <<'EOF'
2026-07-01 ERROR connection failed
2026-07-01 WARNING disk low
2026-07-01 INFO service ok
EOF
grep ERROR /tmp/sample.logSample output:
2026-07-01 ERROR connection failedThe same pattern works on stdin without a file argument:
echo -e 'alpha\nbeta\ngamma' | grep betaSample output:
betagrep is case-sensitive by default — add -i when log levels vary in capitalization.
Essential OR several keywords with -E
Extended regex lets you alternate patterns with | in one pass instead of running grep multiple times.
Run the command:
grep -Ei 'error|warning' /tmp/sample.logSample output:
2026-07-01 ERROR connection failed
2026-07-01 WARNING disk low-E is required for | to mean OR. Without it, the pipe is a literal character. Combine with -i when case varies.
Common Read many patterns from a file with -f
Long keyword lists belong in a pattern file — one term per line — instead of a long command line.
Run the commands:
cat > /tmp/patterns.txt <<'EOF'
error
warning
failed
EOF
grep -i -f /tmp/patterns.txt /tmp/sample.logSample output:
2026-07-01 ERROR connection failed
2026-07-01 WARNING disk lowAny line matching any pattern in the file is printed. Use grep -E -f when patterns in the file are extended regex.
Common Whole-word match with -w
Without -w, searching for log also matches login and catalog. -w requires word boundaries.
Run the command:
echo 'log login logout' > /tmp/words.txt
grep -w log /tmp/words.txtSample output:
log login logoutThe line is printed because it contains the standalone word log. login and logout are not matched as the word log.
Common Whole-line match with -x
-x keeps only lines where the entire line equals the pattern — useful for exact status codes or marker lines.
Run the command:
echo -e 'exact line\nnot exact line here' > /tmp/lines.txt
grep -x 'exact line' /tmp/lines.txtSample output:
exact lineThe second line is skipped because extra text follows the pattern.
Common Context before and after with -B, -A, -C
Stack traces and multi-field log entries make more sense with neighboring lines.
Run the commands:
grep -B1 -i warning /tmp/sample.log
grep -A1 -i error /tmp/sample.log
grep -C1 -i warning /tmp/sample.logSample output (-B1):
2026-07-01 ERROR connection failed
2026-07-01 WARNING disk lowSample output (-A1):
2026-07-01 ERROR connection failed
2026-07-01 WARNING disk low-C N prints N lines on both sides. Use one context flag per run — combining -A and -B stacks both.
Common Literal dots with -F
In basic regex, . matches any character. -F treats the pattern as plain text.
Run the command:
echo 'rate.limit exceeded' >> /tmp/sample.log
grep -F 'rate.limit' /tmp/sample.logSample output:
rate.limit exceededUse -F for URLs, package names, and any string with regex metacharacters.
Advanced Extract matching parts with -o
-o prints only the substring that matched — not the full line. Pair with -E or -P for structured data.
Run the command:
echo 'client 192.168.1.10 connected' >> /tmp/sample.log
grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' /tmp/sample.logSample output:
192.168.1.10Repeat matches on one line each get their own output line — handy for pulling IPs or timestamps from verbose logs.
Advanced Lines that contain two words with -P
Perl regex supports lookaheads — match a line only when it contains multiple terms in any order.
Run the command:
echo '2026-07-01 error database timeout' >> /tmp/sample.log
grep -P '(?=.*error)(?=.*database)' /tmp/sample.logSample output:
2026-07-01 error database timeoutGNU grep on Ubuntu uses PCRE2 for -P. For portable scripts without -P, use grep -E 'error.*database|database.*error' instead.
Advanced Extract text between markers with -oP
Lookbehind and lookahead delimiters pull out the middle of a field without printing the markers.
Run the command:
echo 'start payload end' | grep -oP '(?<=start ).*(?= end)'Sample output:
payloadKeep patterns as simple as possible — complex -P regex is harder to port than -E alternation.
grep — when to use / when not
| Use pattern-focused grep when | Use something else when |
|---|---|
|
|
grep vs sed
| grep | sed | |
|---|---|---|
| Job | Filter and print matching lines | Transform, delete, or substitute text |
| Output | Lines (or -o fragments) that match |
Modified stream |
| Regex | Line filter | Line and substitution patterns |
| Best for | "Show me errors in this log" | "Replace every foo with bar in place" |
Many pipelines chain them: grep -E 'error|warn' app.log | sed 's/ERROR/[E]/' for display tweaks.
grep — interview corner
When do you use grep -E?
Basic grep treats |, +, and ? as literals unless escaped. -E (extended regex) enables alternation and modern quantifiers without backslash clutter.
grep -E 'error|warning|critical' app.logA strong answer is:
"grep -E for OR and grouping — it's what egrep used to be on GNU systems; I use it whenever the pattern has a pipe."
What is the difference between grep -F and grep -E?
-F is fixed-string mode — fastest when the pattern has dots, brackets, or other regex metacharacters. -E is for real regex with alternation and repetition.
A strong answer is:
"-F for literal strings like hostnames or rate.limit; -E when I need regex logic like error|warn or [0-9]+."
How does grep -f work?
Each non-empty line in the file is a separate pattern. grep prints lines that match any of them.
grep -f keywords.txt application.logA strong answer is:
"grep -f reads one pattern per line — I maintain alert keyword lists in a file instead of huge command lines."
What do -w and -x change?
-w matches only when the pattern is a complete word (word boundaries on both sides). -x matches only when the entire line equals the pattern.
A strong answer is:
"-w stops log from matching login; -x is for exact-line matches like a status code line with nothing else on it."
When is grep -P appropriate?
-P enables Perl features — lookaheads, \d, non-greedy .*?. GNU grep on Linux supports it via PCRE2; BSD grep and older systems may not.
A strong answer is:
"I use -P on GNU grep for lookaheads and convenient escapes; for portable scripts I rewrite with -E or awk."
What does 'conflicting matchers specified' mean?
grep rejects incompatible mode flags in one invocation — for example -E and -F together, or mixing engines that contradict each other.
A strong answer is:
"Pick one engine per run — -E, -F, or -P — not two at once; split the job into two greps if needed."
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| matches a literal pipe |
Basic regex mode | Add -E or escape: grep 'error|warn' |
. matches any character |
Regex metacharacter | Use -F for literals or escape the dot |
login matches search for log |
Substring match | Add -w for whole words |
-P fails on another OS |
Non-GNU grep | Use -E alternation or awk |
conflicting matchers specified |
-E and -F together |
Use one engine per command |
| Pattern file matches nothing | Blank lines or wrong case | Clean the file; try -i |
-f regex not working |
File has ERE syntax | Add -E with -f |
