2.3 grep and Regular Expressions for Text Analysis
Key Takeaways
- grep searches lines of text for patterns; exit status 0 means match found, 1 means no match, 2 means error—useful in scripts and checks.
- Essential options for EX200: `-i` ignore case, `-v` invert, `-r/-R` recurse, `-n` line numbers, `-c` count, `-l` filenames, `-E` extended regex (egrep).
- Basic regular expressions (BRE) treat `? + | ( )` as literals unless escaped; extended regex (ERE with `grep -E`) gives them special meaning.
- Anchor patterns with `^` and `$`, use `.` for any character, `*` for “previous atom zero or more times,” and character classes like `[0-9]` or `[[:space:]]`.
- Combine grep with pipes and redirection to analyze logs, configs, and command output under time pressure without opening full files in an editor.
2.3 grep and Regular Expressions for Text Analysis
Quick Answer: Use
grep [options] pattern [file...]to select matching lines. Prefergrep -Efor extended regular expressions,-ifor case-insensitive search,-vto invert, and-rto recurse directories. Exit status 0 means at least one match.
The EX200 objective Use grep and regular expressions to analyze text is how you extract signal from noisy systems: locate directives in /etc, find failed logins, filter ps or ss output, and verify that a change “took” without reading multi-thousand-line files by hand.
grep Fundamentals
grep pattern file
grep pattern file1 file2
command | grep pattern
If multiple files are named, grep prefixes each hit with the filename. From a pipe, input has no filename unless you use tools like grep -H or prefix with process substitution.
Exit status:
| Status | Meaning |
|---|---|
| 0 | One or more lines matched |
| 1 | No lines matched |
| 2 | Error (missing file, bad option, etc.) |
grep -q '^root:' /etc/passwd && echo "root account exists"
-q (quiet) suppresses output; only the exit status matters—ideal for scripts and quick checks.
High-Value Options for the Exam
| Option | Purpose | Example |
|---|---|---|
-i | Case-insensitive | grep -i error /var/log/messages |
-v | Invert match (non-matching lines) | grep -v '^#' /etc/ssh/sshd_config |
-n | Show line numbers | grep -n PermitRootLogin /etc/ssh/sshd_config |
-c | Count matching lines | grep -c 'Failed password' /var/log/secure |
-l | List only filenames with matches | grep -rl SELinux /etc |
-L | List filenames without matches | grep -rL Timeout /etc/ssh |
-r or -R | Recurse directories | grep -r 'ListenAddress' /etc/ssh |
-E | Extended regular expressions | `grep -E 'error |
-F | Fixed strings (no regex) | grep -F '***' file |
-w | Whole word match | grep -w root /etc/passwd |
-x | Whole line match | grep -x 'root' names.txt |
-A/-B/-C N | Context after/before/both | grep -A2 -B2 error log |
-e | Multiple patterns | grep -e foo -e bar file |
--color=auto | Highlight matches (when supported) | grep --color=auto error log |
On RHEL, egrep is historically grep -E and fgrep is grep -F. Prefer the long forms grep -E / grep -F for clarity and portability in scripts.
Filtering Config Files
System configs are full of comments and blank lines. A classic RHCSA pattern:
grep -v '^#' /etc/ssh/sshd_config | grep -v '^$'
# or
grep -E -v '^#|^$' /etc/ssh/sshd_config
Find active (possibly commented) settings:
grep -n -i 'permitrootlogin' /etc/ssh/sshd_config
grep -n -E '^[#[:space:]]*Port[[:space:]]+' /etc/ssh/sshd_config
After editing, re-grep to prove the value to yourself before moving on:
grep -E '^PermitRootLogin\s+no' /etc/ssh/sshd_config
Recursive Search Across Trees
grep -r '192.168.10' /etc 2>/dev/null
grep -rI 'TODO' /usr/local/share/app 2>/dev/null
-I skips binary files (useful under /usr). Always consider redirecting stderr when searching system trees as a non-root user to avoid drowning in permission errors.
Limit by glob:
grep -r --include='*.conf' 'ServerName' /etc/httpd 2>/dev/null
grep -r --exclude-dir={proc,sys,dev} pattern / 2>/dev/null # unquoted braces: bash expands to three --exclude-dir flags
grep -r --exclude-dir=proc --exclude-dir=sys --exclude-dir=dev pattern / 2>/dev/null # explicit form; careful: slow
On the exam, prefer narrow paths (/etc/ssh, /var/log/httpd) over scanning /.
Regular Expressions: BRE vs ERE
grep default dialect is Basic Regular Expressions (BRE). grep -E uses Extended Regular Expressions (ERE).
| Feature | BRE (grep) | ERE (grep -E) |
|---|---|---|
| Any char | . | . |
| Repeat previous 0+ | * | * |
| Repeat 1+ | \+ | + |
| Optional | \? | ? |
| Alternation | | | ` |
| Grouping | \( \) | ( ) |
| Anchor start/end | ^ $ | ^ $ |
| Escape digit class etc. | same ideas | same ideas |
Exam practical rule: When you need |, +, ?, or unescaped (), use grep -E so patterns stay readable and you avoid under-escaping mistakes.
Pattern Building Blocks
Anchors and wildcards
grep '^root' /etc/passwd # line starts with root
grep 'bash$' /etc/passwd # line ends with bash
grep '^$' file # empty lines
grep 'r.t' file # r, any char, t (rat, rot, r t, …)
Quantifiers (ERE form)
grep -E 'o+' file # one or more o
grep -E 'colou?r' file # color or colour
grep -E 'file[0-9]{2,4}' file # file + 2 to 4 digits
In BRE, write \{2,4\} instead of {2,4}.
Character classes
grep -E '[A-Z]' file # any uppercase ASCII letter
grep -E '[0-9]+' file # digits
grep -E '[^#]' file # lines with a non-# character (careful)
grep -E '[[:space:]]' file # whitespace (POSIX class)
grep -E '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' file
POSIX classes like [[:alpha:]], [[:alnum:]], [[:space:]], [[:digit:]] are safer across locales than hard-coded ranges for some data, though many exam tasks use simple [0-9] and [A-Za-z].
Alternation
grep -E 'error|fail|denied' /var/log/secure
grep -E '^(allow|deny)' rules.txt
Word boundaries
grep -w root /etc/passwd # whole word root
grep -E '\<root\>' /etc/passwd # BRE/ERE word boundary syntax (GNU)
Prefer -w when you simply need whole-word matching without writing boundaries by hand.
Analyzing Command Output with Pipes
ss -tulpn | grep -E ':22\s'
ps aux | grep -E '[h]ttpd' # avoid matching the grep process itself
journalctl -u sshd --no-pager | grep -i failed | tail -n 50
rpm -qa | grep -i ^kernel
dnf history | grep -i install
The [h]ttpd trick works because the character class does not match the literal pattern string in the grep command line the same way a plain httpd pattern does—handy in process lists.
Count unique failed users from a secure log (illustrative):
grep 'Failed password' /var/log/secure | awk '{print $(NF-5)}' | sort | uniq -c | sort -nr
You may not need awk depth on every task; the point is that grep is the first filter in a pipeline.
Practical Scenarios
Scenario 1: Confirm a user has /bin/bash as shell
grep -E '^alice:.*:/bin/bash$' /etc/passwd
Scenario 2: Strip comments from a cron file before reading
grep -E -v '^[[:space:]]*(#|$)' /etc/cron.d/backup
Scenario 3: Find which file under /etc/sysconfig mentions a NIC name
grep -r --include='*' 'enp0s3' /etc/sysconfig 2>/dev/null
Scenario 4: Invert match to remove header lines
df -h | grep -v '^Filesystem'
Scenario 5: Case-insensitive recursive search with line numbers for a ticket
grep -rni 'timeout' /etc/httpd 2>/dev/null | tee /root/timeout-hits.txt
Common Traps
- Forgetting
-Ewhen using|— in BRE, unescaped|is literal; your alternation silently fails to alternate. - Greedy expectations —
.*can match more than you visualize; anchor patterns with^$when matching whole fields. - Special characters in patterns —
.matches any character; escape dots in IPs:192\.168\.1\.10or usegrep -F '192.168.1.10'. - Binary file “matches” — grep may print “Binary file X matches”; use
-ato treat as text or-Ito skip. - Locale surprises — character ranges can depend on
LANG; for strict ASCII digits,[0-9]or[[:digit:]]is usually fine on exam defaults. - Searching live logs you cannot read — permission denied means escalate or pick a readable journal with
journalctlas root.
BRE Escape Cheatsheet (when not using -E)
grep 'colour\?' file # optional u in BRE
grep 'copy\+' file # one or more
grep 'cat\|dog' file # alternation in BRE
grep '\(error\|fail\)' file # group + alternation
grep 'id=[0-9]\{2,4\}' file # bounded repeat
If this feels noisy mid-exam, switch mental model to grep -E and write natural ERE.
Related Tools (Do Not Confuse)
| Tool | Role vs grep |
|---|---|
rg (ripgrep) | Faster recursive search—may not be installed on exam; stick to grep |
ag / ack | Same caution—do not depend on extras |
sed -n '/pat/p' | Editing-oriented; grep is clearer for pure filtering |
awk | Field processing after grep narrows lines |
less + /pattern | Interactive browsing, not non-interactive filters |
RHCSA expects grep competence specifically; do not spend time installing alternative search tools during the exam.
Verification Mindset
After configuration tasks, use grep as a self-check:
grep -E '^server\s+' /etc/chrony.conf
grep -E '^PermitRootLogin\s+prohibit-password' /etc/ssh/sshd_config || \
grep -E '^PermitRootLogin\s+no' /etc/ssh/sshd_config
systemctl is-enabled firewalld | grep -x enabled
Piping systemctl or other status commands into grep -x makes pass/fail obvious in scripts and in your own final sweep before time expires.
Section Checkpoint
You should be able to select lines with literal and regex patterns, invert and recurse safely, explain BRE vs ERE for | + ? ( ), anchor matches, and integrate grep into pipes with redirection. That skill set turns multi-megabyte logs and dense configs into exam-sized answers.
Which command performs a case-insensitive search for lines containing either error or failed in /var/log/messages using extended regular expressions?
What does grep -v '^#' /etc/ssh/sshd_config accomplish?
In default BRE mode (plain grep without -E), how must you write alternation between cat and dog?
A command pipeline ends with grep -q 'active'. Why might an administrator use -q?