grep
grep#
Concepts#
What Is grep?#
grep (Global Regular Expression Print) searches for patterns in text and prints matching lines. It is one of the most frequently used commands on Linux. You use it to find things — in files, in command output, in logs.
grep "pattern" filename
# Prints every line in filename that contains "pattern"
Basic Usage#
# Search for a string in a file
grep "error" /var/log/syslog
# Search in multiple files
grep "error" /var/log/*.log
# Search from stdin (piped input)
cat /etc/passwd | grep "bash"
dmesg | grep "usb"
Common Options#
| Option | Meaning | Example |
|---|---|---|
-i |
Case insensitive | grep -i "error" log.txt |
-n |
Show line numbers | grep -n "TODO" code.py |
-c |
Count matching lines | grep -c "error" log.txt |
-l |
List filenames with matches (not the lines) | grep -l "password" /etc/* |
-L |
List filenames WITHOUT matches | grep -L "error" *.log |
-v |
Invert match (lines that do NOT match) | grep -v "^#" config.txt |
-r |
Recursive (search all files in directories) | grep -r "TODO" /project/ |
-w |
Match whole words only | grep -w "log" file.txt (not “login”) |
-x |
Match entire line | grep -x "exact line" file.txt |
-o |
Print only the matching part, not the whole line | grep -o "[0-9]*" file.txt |
-A N |
Show N lines after each match | grep -A 3 "error" log.txt |
-B N |
Show N lines before each match | grep -B 2 "error" log.txt |
-C N |
Show N lines before and after (context) | grep -C 5 "error" log.txt |
--color |
Highlight matches (usually default) | grep --color "pattern" file |
Combining Options#
Options can be combined freely:
# Case insensitive, with line numbers, recursive
grep -inr "error" /var/log/
# Count lines NOT matching "comment", case insensitive
grep -civ "^#" config.txt
# Show filenames with matches, recursive, case insensitive
grep -rli "password" /etc/ 2>/dev/null
Regular Expressions#
grep supports regular expressions (regex) — patterns that describe text rather than matching literally.
Basic Regex (BRE) — Default#
| Pattern | Matches |
|---|---|
. |
Any single character |
* |
Zero or more of the previous character |
^ |
Beginning of line |
$ |
End of line |
[abc] |
Any one character: a, b, or c |
[a-z] |
Any lowercase letter |
[0-9] |
Any digit |
[^abc] |
Any character EXCEPT a, b, c |
\ |
Escape a special character |
Examples:
# Lines starting with "#" (comments)
grep "^#" /etc/fstab
# Lines ending with "bash"
grep "bash$" /etc/passwd
# Lines starting with a letter
grep "^[a-zA-Z]" file.txt
# Empty lines
grep "^$" file.txt
# Lines that are NOT empty
grep -v "^$" file.txt
# "col" followed by any character then "r" (color, colour, etc.)
grep "col.r" file.txt
Extended Regex (ERE) — With grep -E or egrep#
Extended regex adds more operators without needing backslash escapes:
| Pattern | Matches |
|---|---|
+ |
One or more of the previous character |
? |
Zero or one of the previous character |
{n} |
Exactly n occurrences |
{n,m} |
Between n and m occurrences |
| (BRE) or ` |
` (ERE) |
() |
Grouping |
# Use -E for extended regex
grep -E "error|warning|critical" /var/log/syslog
# One or more digits
grep -E "[0-9]+" file.txt
# IP address pattern (simplified)
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" file.txt
# Optional "s" (match "color" and "colors")
grep -E "colors?" file.txt
# Lines with exactly 3 characters
grep -E "^.{3}$" file.txt
grep -P — Perl-Compatible Regex#
For advanced patterns, use -P (available on most systems via grep compiled with PCRE):
# Lookahead, lookbehind, \d for digits, etc.
grep -P "\d{3}-\d{4}" file.txt # phone pattern: 123-4567
grep -P "(?<=@)\w+" emails.txt # domain part of emails
Recursive Search in Directories#
# Search all files in a directory tree
grep -r "TODO" /path/to/project/
# Recursive, with line numbers, specific file types
grep -rn --include="*.py" "import os" /project/
# Exclude directories
grep -rn --exclude-dir=".git" "function" /project/
# Exclude file patterns
grep -rn --exclude="*.log" "error" /var/
Fixed Strings with grep -F (or fgrep)#
When you want to search for a literal string (no regex):
# These special characters are treated literally
grep -F "user.name[0]" config.txt
# Without -F, the . and [ would be regex operators
Lab#
Exercise 1: Basic grep#
mkdir -p ~/lab/grep
cd ~/lab/grep
# Create a sample file
cat > sample.txt << 'EOF'
# Configuration file
server_name=localhost
server_port=8080
# database settings
db_host=localhost
db_port=5432
db_name=myapp
db_user=admin
db_password=secret123
# logging
log_level=INFO
log_file=/var/log/myapp.log
debug_mode=false
EOF
# Search for "db"
grep "db" sample.txt
# Case insensitive search
grep -i "SERVER" sample.txt
# Show line numbers
grep -n "localhost" sample.txt
# Count matches
grep -c "db" sample.txt
Exercise 2: Inverse Matching and Comments#
cd ~/lab/grep
# Show only non-comment lines (lines not starting with #)
grep -v "^#" sample.txt
# Show non-empty, non-comment lines
grep -v "^#" sample.txt | grep -v "^$"
# Count active configuration lines
grep -cv "^#" sample.txt
Exercise 3: Regular Expressions#
cd ~/lab/grep
# Lines starting with "db"
grep "^db" sample.txt
# Lines ending with a number
grep "[0-9]$" sample.txt
# Lines containing a port number (4-5 digits)
grep -E "[0-9]{4,5}" sample.txt
# Find lines with "host" OR "port"
grep -E "host|port" sample.txt
# Find lines with exactly "localhost"
grep -w "localhost" sample.txt
Exercise 4: Searching System Files#
# Find all users with bash as their shell
grep "bash$" /etc/passwd
# Find your user
grep $(whoami) /etc/passwd
# Count how many system services exist
grep -c "nologin" /etc/passwd
# Find lines with "nameserver" in resolv.conf
cat /etc/resolv.conf | grep "nameserver"
Exercise 5: Recursive Search#
# Search for a word in all files under /etc (may need sudo for some)
sudo grep -rl "AllowOverride" /etc/ 2>/dev/null
# Search only in .conf files
sudo grep -rn --include="*.conf" "listen" /etc/ 2>/dev/null | head -10
# Search with context (3 lines before and after)
grep -C 3 "password" ~/lab/grep/sample.txt
Exercise 6: Practical Pipelines#
# Find all installed packages with "python" in the name
dpkg -l | grep "python" | head -10
# Find processes using the word "bash"
ps aux | grep "bash"
# Note: grep itself often shows up — filter it out:
ps aux | grep "[b]ash"
# Find lines in syslog from today (approximate)
sudo grep "$(date +%b\ %d)" /var/log/syslog 2>/dev/null | tail -5
# Extract IP addresses from a log (simplified)
echo "Connection from 192.168.1.100 port 22" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"
Exercise 7: grep with Context#
cd ~/lab/grep
# Create a log-like file
cat > app.log << 'EOF'
2024-10-15 08:00:01 INFO Application started
2024-10-15 08:00:02 INFO Loading configuration
2024-10-15 08:00:03 INFO Database connected
2024-10-15 08:05:00 WARN High memory usage: 85%
2024-10-15 08:05:01 INFO Running garbage collection
2024-10-15 08:10:00 ERROR Connection timeout to API
2024-10-15 08:10:01 ERROR Retrying connection (1/3)
2024-10-15 08:10:05 INFO Connection restored
2024-10-15 08:15:00 INFO Processing batch job
2024-10-15 08:20:00 WARN Slow query detected: 5.2s
EOF
# Show errors with 2 lines of context
grep -C 2 "ERROR" app.log
# Show only warnings and errors
grep -E "WARN|ERROR" app.log
# Show everything EXCEPT INFO
grep -v "INFO" app.log
# Count each log level
echo "INFO: $(grep -c 'INFO' app.log)"
echo "WARN: $(grep -c 'WARN' app.log)"
echo "ERROR: $(grep -c 'ERROR' app.log)"
# Clean up
cd ~
rm -rf ~/lab/grep
Review#
1. What does grep do?
grep searches for a pattern in text (files or stdin) and prints every line that matches. The name stands for “Global Regular Expression Print.”
2. How do you do a case-insensitive search?
grep -i "pattern" file — the -i flag makes the search case-insensitive.
3. How do you search recursively through a directory?
grep -r "pattern" /path/ — the -r flag searches all files in the directory and its subdirectories. Add --include="*.ext" to filter by file type.
4. What does `grep -v` do?
It inverts the match — showing lines that do NOT contain the pattern. For example, grep -v "^#" config.txt shows all non-comment lines.
5. What is the difference between `grep` and `grep -E`?
grep uses Basic Regular Expressions (BRE) where +, ?, |, {}, and () must be escaped with \. grep -E uses Extended Regular Expressions (ERE) where these operators work without escaping. Use -E for complex patterns.
6. How do you show lines around a match for context?
-A N shows N lines after, -B N shows N lines before, -C N shows N lines before and after. Example: grep -C 3 "error" log.txt.
7. How do you search for a literal string containing regex special characters?
Use grep -F "literal.string[0]" — the -F flag treats the pattern as a fixed string, not a regular expression.
Previous: Streams, Redirection, and Pipes | Next: sed and awk