Regular expressions are the grammar behind grep, sed, awk, and most search boxes you have ever used. Learning to read them — before writing them — is the practical path, and it takes one page.
The characters that do work #
Everything in a regex is literal except a small cast:
| Symbol | Matches | |
|---|---|---|
. | Any single character | |
^ / $ | Start / end of the line | |
* / + / ? | 0+, 1+, or optional repeat of the previous | |
[abc] / [a-z] | One character from a set or range | |
[^abc] | One character NOT in the set | |
(abc) | A group, for repeats and capture | |
| `\ | ` | Alternation in extended regex |
\d \w \s | Digit, word char, whitespace (in some tools) |
Everything else matches itself. error is a perfectly good regex; so is ^2026-10-2\d.
Reading patterns aloud #
The skill is saying the pattern in words before typing it. Some workhorses:
^ERROR lines that START with ERROR
\.log$ lines that END with .log
^[a-z]+@[a-z]+ local-part of simple emails
(timeout|retry) either word
[0-9]{2,4} two to four digits
Building them is incremental: start with a literal that matches, add one construct, re-test. grep -o shows exactly what matched, which makes each step verifiable:
$ grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' access.log | head
The two regex dialects #
grep defaults to basic regular expressions, where +, ?, (, and | need backslashes. Add -E for extended regex and they work bare — the saner dialect, and the reason -E appears throughout this series:
$ grep 'error\(1\|2\)' file.log # basic
$ grep -E 'error(1|2)' file.log # extended
For the tools that consume these patterns, continue with sed for editing and grep for filtering — then put the pieces together in unix pipes in practice. The terminal notes series covers each step.
