grep and Regular Expressions
grep (Global Regular Expression Print) searches input for lines matching a pattern and prints them — it's one of the most frequently used tools in any shell workflow, from filtering log files to searching source code. Its real power comes from regular expressions (regex): a compact language for describing text patterns far more flexible than literal substring matching. Understanding grep's regex dialects and its most useful flags turns it from a simple search tool into a precise text-filtering instrument.
Cricket analogy: grep is like a scout scanning years of match footage for every instance a batter played the reverse sweep, and regex is what lets that search go beyond just 'reverse sweep' to flexible patterns like any sweep shot variant at all.
Basic vs extended regular expressions
GNU grep supports two regex dialects: Basic Regular Expressions (BRE), the default, and Extended Regular Expressions (ERE), enabled with -E (or via the egrep alias, which is deprecated in favor of grep -E). In BRE, metacharacters like +, ?, |, (, and ) are treated as literal characters unless escaped with a backslash (\+, \?, \|); in ERE they are metacharacters by default and must be escaped to be literal. GNU grep also supports -P for Perl-compatible regular expressions (PCRE), which adds features like non-greedy quantifiers (*?), lookahead ((?=...)), and \d/\w/\s shorthand classes not available in POSIX regex at all.
Cricket analogy: BRE versus ERE is like the difference between old-school scoring notation where symbols mean nothing special unless marked, versus modern scoring apps where symbols like '4' or '6' are always meaningful markers unless you escape them as literal digits written out.
# Basic literal search, case-insensitive, recursive
grep -ri 'connection refused' /var/log/
# Extended regex: alternation and quantifiers without backslashes
grep -E '(error|warn|fatal)' app.log
grep -E 'user[0-9]{3,5}@' users.csv
# Show line numbers and 2 lines of context around each match
grep -n -C 2 'NullPointerException' server.log
# Invert match: lines NOT containing a pattern
grep -v '^#' /etc/ssh/sshd_config
# Count matches, and list only filenames that match
grep -c 'TODO' *.py
grep -l 'import requests' *.py
# Whole-word match and PCRE lookahead (GNU grep -P)
grep -w 'cat' animals.txt
grep -P '\d{3}-\d{2}-\d{4}' records.txt # SSN-like patternAnchors, character classes, and quantifiers
^ anchors a match to the start of a line and $ to the end, so ^ERROR only matches lines beginning with ERROR. Character classes like [abc] match any one of the listed characters, [^abc] matches any character except those listed, and POSIX classes like [[:digit:]], [[:alpha:]], and [[:space:]] are portable across locales in a way [0-9] isn't guaranteed to be everywhere (though in practice [0-9] works fine on virtually all modern Linux systems). Quantifiers control repetition: * means zero or more, + means one or more (ERE/PCRE, or \+ in BRE), ? means zero or one, and {n,m} means between n and m repetitions. Combining these lets you build precise patterns, e.g. ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ as a rough (not fully correct) IPv4 matcher.
Cricket analogy: Using ^ERROR to anchor a match to line-start is like a scorer only counting a boundary if the ball crosses the rope on the very first bounce, and quantifiers like {1,3} are like specifying a batter must have scored between 1 and 3 runs off that specific delivery.
grep's name comes from the ed editor command g/re/p — 'globally search for a regular expression and print matching lines' — a piece of Unix history baked directly into the tool's name, dating back to the earliest versions of Unix in the early 1970s.
Unquoted glob-like patterns passed to grep can be expanded by the shell before grep ever sees them. For example, grep [test].log *.log risks the shell interpreting [test] as a filename glob if matching files exist in the current directory. Always quote your pattern: grep '[test]' *.log.
- grep searches text line by line for a pattern and prints matching lines; -E enables extended regex, -P enables Perl-compatible regex.
- In BRE (default), +, ?, |, (, ) are literal unless escaped; in ERE they're metacharacters unless escaped.
- ^ and $ anchor to line start/end; character classes ([abc], [^abc], [[:digit:]]) match sets of characters.
- Useful flags: -i (case-insensitive), -v (invert match), -n (line numbers), -c (count), -l (filenames only), -r (recursive), -w (whole word), -C (context lines).
- Always quote regex patterns to prevent the shell from glob-expanding special characters before grep runs.
- PCRE mode (-P) adds features POSIX regex lacks, like \d, \w, and non-greedy quantifiers.
Practice what you learned
1. In default (BRE) grep, how must you write a pattern to match 'one or more' repetitions?
2. Which grep flag inverts matching, printing only lines that do NOT match the pattern?
3. What does the pattern `^ERROR` match that `ERROR` alone would not?
4. Which grep option enables Perl-compatible regular expressions, adding shorthand classes like \d and \w?
5. Why should you quote a grep pattern like `grep [abc] file.txt` as `grep '[abc]' file.txt`?
Was this page helpful?
You May Also Like
sed: Stream Editing Basics
Learn sed, the non-interactive stream editor, for search-and-replace, line deletion, and text transformation directly from the command line or in scripts.
awk Basics
Learn awk, the field-oriented text processing language, to extract columns, compute aggregates, and transform structured text like logs and CSVs.
Pipes and Redirection
Learn how the shell wires standard input, output, and error between commands and files using redirection operators and pipes to build powerful command chains.
Reading and Managing Logs (journalctl, /var/log)
Master the two dominant Linux logging models — the systemd journal and traditional flat-file logs in /var/log — to diagnose issues and manage log retention.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics