Table of Contents

Regular Expressions

Same pattern means different things in different tools. This is the table that resolves it.

Regex Flavors by Tool

Tool Default Upgrade flag
grep BRE -E for ERE, -P for PCRE
sed BRE -E (or -r) for ERE
awk ERE-ish gawk has more
rg Rust regex no backrefs or lookaround
perl PCRE
[[ =~ ]] in bash ERE

The Differences That Matter

Feature BRE (grep/sed default) ERE (-E, awk, bash =~)
+, ? quantifiers \+, \? (escaped = special) bare + ?
groups \( \) ( )
alternation \\| |
{n,m} counts \{n,m\} {n,m}
backrefs in pattern \1 \1 for ERE search; not in rg

Escaped-vs-bare flips between BRE and ERE: in BRE, (a) is literal parens and \(a\) is a group; in ERE it's the opposite. When unsure, use -E.

Universal building blocks

.        any char            \.        literal dot
* + ?    0+, 1+, 0-1         ^ $       line start/end
[abc]    set                 [^abc]    negated set
[a-z]    range               {n,m}     counts: {3} {2,} {2,5}
x|y      alternation (ERE)   (x|y)     group

POSIX classes (work everywhere, even BRE):

[[:digit:]]  [[:alpha:]]  [[:alnum:]]  [[:space:]]  [[:upper:]]  [[:lower:]]
[[:punct:]]  [[:print:]]  [[:blank:]]  [[:xdigit:]]

GNU extras (work in GNU grep/sed both flavors): \b word boundary, \</\> word edges, \w word char, \s whitespace, \B.

PCRE/Rust extras (grep -P, rg, perl): \d \D \s \S \w \W, non-greedy *?, named groups (?P<n>..), lookahead (?=..) (?!..). Note: rg's default engine supports NO lookaround/backrefs: add rg -P to get PCRE2 when you need them.

Practical translations

# same task, three tools
grep -E '^(Mon|Tue)' f         sed -nE '/^(Mon|Tue)/p' f    rg '^(Mon|Tue)' f
 
# BRE version of the ERE "(a|b)+"
grep 'x\(a\|b\)\+y'            # hard to read: use -E instead
 
# IPs: ERE
grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}'
# BRE equivalent (don't do this)
grep -o '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}'

Substitution notes

When Regex Fails

Line-oriented tools will not do it with $/. alone.

See Also