POSIX defines two regular-expression dialects — Basic (BRE) and Extended (ERE) — and the difference between them trips up almost everyone who moves between grep, sed and awk. The same pattern can mean completely different things depending on which flavor a tool uses by default. This reference puts the two dialects side by side, lists the standard bracket character classes, and tells you which tool speaks which dialect.
BRE and ERE: the two POSIX dialects
In a Basic Regular Expression the special characters that do grouping,
alternation and counting are written with a leading backslash: grouping is
\( \), alternation is \|, and a bound is \{m,n\}. Without the backslash
those characters are literal. In an Extended Regular Expression the same
constructs are written bare — ( ), |, {m,n} — and a backslash makes them
literal instead. The anchors ^ and $, the dot ., the star *, and bracket
expressions [...] behave the same in both dialects.
POSIX has no single-letter shorthand classes. Instead it provides named
bracket character classes like [:alpha:], [:digit:] and [:space:], which
must appear inside a bracket expression — so a digit is [[:digit:]]. This keeps
matching correct across locales and character sets where the ASCII ranges alone
would be wrong.
BRE vs ERE at a glance
| Feature | BRE | ERE |
|---|---|---|
| Grouping | \( \) | ( ) |
| Alternation | | (GNU ext.) | ` |
| One-or-more | \+ (GNU ext.) | + |
| Zero-or-one | \? (GNU ext.) | ? |
| Bounds | \{m,n\} | {m,n} |
| Literal brace | { | \{ |
| Backreferences | \1 through \9 | not in strict POSIX |
Tool flavor defaults
| Tool | Default dialect | Override flag |
|---|---|---|
grep | BRE | -E for ERE, -P for PCRE (GNU) |
sed | BRE | -E (GNU/macOS) or -r (older GNU) |
awk | ERE | no flag needed |
egrep | ERE | deprecated alias for grep -E |
find -regex | Emacs RE (BRE-like) | -regextype posix-extended |
POSIX bracket character classes
These are the portable alternatives to PCRE shorthand classes like \d and \w:
[[:alpha:]] letter (locale-aware)
[[:digit:]] 0-9
[[:alnum:]] letter or digit
[[:space:]] whitespace (space, tab, newline, etc.)
[[:upper:]] uppercase letter
[[:lower:]] lowercase letter
[[:punct:]] punctuation
[[:blank:]] space or horizontal tab only
[[:print:]] printable characters
[[:graph:]] printable, non-space characters
Tips and notes
Remember the tool defaults: grep and sed are BRE unless you pass -E, while
awk and egrep are ERE. GNU adds convenience extensions (such as \+ and \?
in BRE) that are not portable to other Unixes, so a script that must run anywhere
should stick to the strict POSIX forms shown in the table. Also note that POSIX
does not guarantee backreferences in ERE — they work in GNU awk and most Linux
implementations but are not part of the standard, so for truly portable scripts
use BRE when you need \1.
Worked example: the same match in three tools
Suppose you want to match a line containing error or warning followed by a
colon. The pattern differs by tool because of the flavor each defaults to:
grep 'error:\|warning:' file # BRE — alternation must be escaped (GNU)
grep -E 'error:|warning:' file # ERE — bare pipe
sed -n '/\(error\|warning\):/p' file # BRE — escaped grouping + alternation
awk '/error:|warning:/' file # ERE — bare metacharacters
Every one of these expresses the same regular language; only the escaping
convention changes. This is the single most common reason a pattern that “worked in
awk” fails when pasted into plain grep.
Portability checklist
- Prefer bracket classes (
[[:digit:]]) over PCRE shorthands (\d) — the latter is silently literal in a strict POSIX engine. - Do not rely on non-greedy quantifiers (
*?,+?): POSIX regex is always greedy. - Anchors
^and$match string start/end, not line boundaries, unless the tool processes input line by line (asgrep,sedandawkdo by default). - When a script must run on both GNU and BSD/macOS userlands, test on both —
sed -Eis portable butsed -ris GNU-only.
Sources
- The Open Group — POSIX.1-2017 Base Specifications, Chapter 9: Regular Expressions — the authoritative BRE/ERE definition.
- GNU grep manual — Basic vs Extended Regular Expressions — the GNU extensions noted above.