folk.zone Wiki

a public knowledge base

Site Tools


terminal:scripting:regex

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

  • sed backrefs in replacement: \1-\9, & = whole match.
  • rg capture replace: rg 'a(\d+)' -r 'num$1' uses $1.
  • Case transforms (GNU sed): sed 's/\(.*\)/\U\1/' uppercases.

When Regex Fails

  • Pattern has |/(/{ and you did not mean regex: grep -F.
  • Greedy .* matched too much: use [^x]* or PCRE .*?.
  • Matching across lines: grep -z, perl -0777, or awk paragraph mode.

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

See Also

terminal/scripting/regex.txt · Last modified: by 127.0.0.1