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.
Last updated: August 2026

2.3 grep and Regular Expressions for Text Analysis

Quick Answer: Use grep [options] pattern [file...] to select matching lines. Prefer grep -E for extended regular expressions, -i for case-insensitive search, -v to invert, and -r to 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:

StatusMeaning
0One or more lines matched
1No lines matched
2Error (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

OptionPurposeExample
-iCase-insensitivegrep -i error /var/log/messages
-vInvert match (non-matching lines)grep -v '^#' /etc/ssh/sshd_config
-nShow line numbersgrep -n PermitRootLogin /etc/ssh/sshd_config
-cCount matching linesgrep -c 'Failed password' /var/log/secure
-lList only filenames with matchesgrep -rl SELinux /etc
-LList filenames without matchesgrep -rL Timeout /etc/ssh
-r or -RRecurse directoriesgrep -r 'ListenAddress' /etc/ssh
-EExtended regular expressions`grep -E 'error
-FFixed strings (no regex)grep -F '***' file
-wWhole word matchgrep -w root /etc/passwd
-xWhole line matchgrep -x 'root' names.txt
-A/-B/-C NContext after/before/bothgrep -A2 -B2 error log
-eMultiple patternsgrep -e foo -e bar file
--color=autoHighlight 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).

FeatureBRE (grep)ERE (grep -E)
Any char..
Repeat previous 0+**
Repeat 1+\++
Optional\??
Alternation|`
Grouping\( \)( )
Anchor start/end^ $^ $
Escape digit class etc.same ideassame 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

  1. Forgetting -E when using | — in BRE, unescaped | is literal; your alternation silently fails to alternate.
  2. Greedy expectations.* can match more than you visualize; anchor patterns with ^ $ when matching whole fields.
  3. Special characters in patterns. matches any character; escape dots in IPs: 192\.168\.1\.10 or use grep -F '192.168.1.10'.
  4. Binary file “matches” — grep may print “Binary file X matches”; use -a to treat as text or -I to skip.
  5. Locale surprises — character ranges can depend on LANG; for strict ASCII digits, [0-9] or [[:digit:]] is usually fine on exam defaults.
  6. Searching live logs you cannot read — permission denied means escalate or pick a readable journal with journalctl as 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)

ToolRole vs grep
rg (ripgrep)Faster recursive search—may not be installed on exam; stick to grep
ag / ackSame caution—do not depend on extras
sed -n '/pat/p'Editing-oriented; grep is clearer for pure filtering
awkField processing after grep narrows lines
less + /patternInteractive 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.

Test Your Knowledge

Which command performs a case-insensitive search for lines containing either error or failed in /var/log/messages using extended regular expressions?

A
B
C
D
Test Your Knowledge

What does grep -v '^#' /etc/ssh/sshd_config accomplish?

A
B
C
D
Test Your Knowledge

In default BRE mode (plain grep without -E), how must you write alternation between cat and dog?

A
B
C
D
Test Your Knowledge

A command pipeline ends with grep -q 'active'. Why might an administrator use -q?

A
B
C
D