6.6 Regular Expressions & grep, egrep, fgrep (103.7)
Key Takeaways
- Regular expressions fall into two primary POSIX standards: Basic Regular Expressions (BRE, default in `grep` and `sed`) and Extended Regular Expressions (ERE, enabled via `grep -E` or `egrep`).
- In BRE, metacharacters `+`, `?`, `{n,m}`, `( )`, and `|` must be escaped with a backslash (`\+`, `\?`, `\{n,m\}`, `\( \)`, `\|`) to activate special meaning; in ERE, they function as metacharacters natively.
- Line anchors match text boundaries: `^` matches line beginning, `$` matches line ending, and `^$` matches empty lines.
- POSIX character classes (e.g. `[[:alnum:]]`, `[[:digit:]]`, `[[:space:]]`) provide locale-independent character matching inside bracket expressions.
- The `grep` family includes `grep` (BRE), `egrep` / `grep -E` (ERE), and `fgrep` / `grep -F` (fixed literal strings, bypassing regex compilation for maximum throughput).
6.6 Regular Expressions & grep, egrep, fgrep
Quick Summary: Regular Expressions (Regex) provide a formal pattern-matching grammar for scanning, parsing, and filtering text streams in Linux. POSIX defines two primary dialects: Basic Regular Expressions (BRE) and Extended Regular Expressions (ERE). Administrators use the
grepfamily—comprising standardgrep(BRE),egrep/grep -E(ERE), andfgrep/grep -F(fixed literal string matching)—to locate log patterns, extract configuration parameters, and audit system files.
1. Regular Expression Flavors: BRE vs. ERE
The fundamental distinction between Basic and Extended Regular Expressions lies in how metacharacters and quantifiers are interpreted by default.
| Regex Feature | Metacharacter | Basic Regular Expression (BRE) Syntax | Extended Regular Expression (ERE) Syntax | Functional Matching Definition |
|---|---|---|---|---|
| Any Character | . | . | . | Matches any single character except newline (\n). |
| Line Start Anchor | ^ | ^ | ^ | Matches the position immediately at the beginning of a line. |
| Line End Anchor | $ | $ | $ | Matches the position immediately at the end of a line. |
| Zero or More | * | * | * | Matches zero or more occurrences of the preceding element. |
| One or More | + | \+ (Requires Backslash) | + (Native) | Matches one or more occurrences of the preceding element. |
| Zero or One | ? | \? (Requires Backslash) | ? (Native) | Matches zero or one occurrence (makes preceding element optional). |
| Interval Count | {n,m} | \{n,m\} (Requires Backslash) | {n,m} (Native) | Matches between $n$ and $m$ occurrences of the preceding element. |
| Alternation (OR) | ` | ` | | (Requires Backslash) | **` |
| Grouping | ( ) | \( \) (Requires Backslash) | ( ) (Native) | Groups sub-expressions for quantifiers or capture boundaries. |
⚠️ LPIC-1 Trap — The Escaping Inversion:
- In BRE (
grep):+,?,{ },( ), and|are treated as literal characters unless escaped with a backslash (\+,\?,\{ \},\( \),\|).- In ERE (
grep -E/egrep):+,?,{ },( ), and|are metacharacters by default. Escaping them (\+) forces literal matching!
2. Anchors, Wildcards & Character Classes
Positional Anchors
^(Caret): Anchors match to the beginning of the line.^rootmatches lines starting withroot.$(Dollar): Anchors match to the end of the line.bash$matches lines ending withbash.^$: Matches lines with zero characters between start and end (empty/blank lines).^root$: Matches lines containing only the exact stringrootand nothing else.
Bracket Expressions (Character Sets)
Bracket expressions define character sets matching any single character contained within the brackets:
[abc]: Matches eithera,b, orc.[a-z]: Matches any lowercase alphabetic letter.[0-9]: Matches any numeric digit.[^abc]: Negation (Inverted Set) — Matches any single character excepta,b, orcwhen^is the first character inside the brackets.
POSIX Character Classes
POSIX defines locale-aware character class aliases that must be enclosed inside an outer set of brackets ([[:class:]]):
| POSIX Class | Equivalent Set | Matches |
|---|---|---|
[[:alnum:]] | [a-zA-Z0-9] | Alphanumeric characters (letters and digits) |
[[:alpha:]] | [a-zA-Z] | Alphabetic letters |
[[:digit:]] | [0-9] | Numeric digits |
[[:lower:]] | [a-z] | Lowercase alphabetic letters |
[[:upper:]] | [a-Z] | Uppercase alphabetic letters |
[[:space:]] | [ \t\n\r\f] | Whitespace characters (space, tab, newline, form feed) |
[[:blank:]] | [ \t] | Horizontal blank space (space and tab only) |
[[:punct:]] | [!"#$%&'()*+,-./:;<=>?@[\]^_{ | }~]` |
[[:xdigit:]] | [0-9a-fA-F] | Hexadecimal digits |
# Match any line containing a 3-digit number:
$ grep '[[:digit:]][[:digit:]][[:digit:]]' /var/log/syslog
3. The grep Family & Command-Line Flags
The GNU grep suite contains three command variants:
grep: Searches files using standard POSIX Basic Regular Expressions (BRE).egrep(orgrep -E): Searches files using Extended Regular Expressions (ERE).fgrep(orgrep -F): Searches for Fixed literal strings. It disables all regex parsing, making it extremely fast when searching for exact strings containing dots, brackets, asterisks, or dollar signs.
Essential grep Command-Line Flags
| Flag | Long Option | Operational Behavior |
|---|---|---|
-i | --ignore-case | Ignores case distinctions in both pattern and input data. |
-v | --invert-match | Inverts selection: outputs only lines that do NOT match the pattern. |
-c | --count | Suppresses normal output; prints only the numeric count of matching lines. |
-l | --files-with-matches | Prints only the names of files containing matches (stops after first match). |
-L | --files-without-match | Prints only the names of files that do NOT contain matches. |
-n | --line-number | Prefixes each output line with its 1-based line number within the file. |
-r / -R | --recursive | Recursively searches all directories (-R follows symlinks). |
-w | --word-regexp | Matches only whole words bounded by non-word characters. |
-x | --line-regexp | Matches only whole lines (pattern must match the entire line from start to end). |
-o | --only-matching | Prints only the exact matching segment of a line rather than the whole line. |
-E | --extended-regexp | Interprets pattern as Extended Regular Expression (ERE, equivalent to egrep). |
-F | --fixed-strings | Interprets pattern as literal text (Fixed strings, equivalent to fgrep). |
-A <N> | --after-context=<N> | Prints <N> lines of trailing context after each match. |
-B <N> | --before-context=<N> | Prints <N> lines of leading context before each match. |
-C <N> | --context=<N> | Prints <N> lines of output context both before and after each match. |
4. Practical Configuration & Log Filtering Recipes
Recipe 1: Stripping Comments and Blank Lines from Config Files
A quintessential system administration task tested on LPIC-1 is inspecting active configuration parameters while filtering out comment lines (starting with #) and empty lines:
# Method 1: Chaining standard grep commands:
$ grep -v '^#' /etc/ssh/sshd_config | grep -v '^$'
# Method 2: Single command using Extended Regular Expressions (ERE):
$ grep -Ev '^(#|$)' /etc/ssh/sshd_config
# Method 3: Handling leading whitespace before comment markers:
$ grep -Ev '^[[:space:]]*(#|$)' /etc/ssh/sshd_config
Input File (/etc/ssh/sshd_config): Filtered Output (`grep -Ev '^(#|$)'`):
┌───────────────────────────────────┐ ┌───────────────────────────────────┐
│ # OpenSSH Daemon Config │ │ Port 22 │
│ Port 22 │ │ PermitRootLogin no │
│ │ │ PasswordAuthentication yes │
│ # Security Settings │ └───────────────────────────────────┘
│ PermitRootLogin no │
│ PasswordAuthentication yes │
└───────────────────────────────────┘
Recipe 2: Matching IP Addresses with ERE
# Find IPv4 addresses in access logs using ERE interval quantifiers:
$ grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' /var/log/nginx/access.log
Recipe 3: Fast Fixed-String Search with fgrep
# Search for literal string '$USER[0]' without escaping metacharacters:
$ fgrep '$USER[0]' /opt/scripts/*.sh
# Or using grep -F:
$ grep -F '$USER[0]' /opt/scripts/*.sh
💡 LPIC-1 Exam Fill-in-the-Blank Alert: What
grepcommand option enables Extended Regular Expression (ERE) pattern interpretation? Answer:-E(or--extended-regexp)
An administrator needs to filter a configuration file to display only active directives, removing all blank lines and all lines that begin with a # comment symbol. Which command accomplishes this?
An administrator needs to search log files for the literal string [ERROR] [192.168.1.1] without having to manually escape the square brackets or periods. Which utility should be used?
Which of the following represents the correct Basic Regular Expression (BRE) syntax when using standard grep to match between 3 and 5 consecutive digits?