Regex tester · Guide

Regex Tester Bash: Matching with =~, grep and sed

Shell regex is three different dialects wearing the same clothes. A pattern that works in `grep -E` fails in plain `grep`, and `sed` needs yet another set of escapes. Knowing which dialect you are in solves most shell regex problems.

The =~ operator

Bash has built-in matching inside [[ ]], using ERE, with captures in BASH_REMATCH:

Shell
if [[ "$input" =~ ^([0-9]{4})-([0-9]{2})$ ]]; then
  year="${BASH_REMATCH[1]}"
  month="${BASH_REMATCH[2]}"
fi

The pattern must be unquoted. Quoting it makes bash treat it as a literal string — a silent failure that produces no match and no error. If the pattern needs to be in a variable, put it there and use the bare variable: [[ $s =~ $re ]].

Three dialects

BRE (basic, plain grep and sed) requires backslashes before +, ?, {}, () and |. ERE (grep -E, sed -E, awk) uses them bare. PCRE (grep -P) adds \d, \w, lookarounds and lazy quantifiers.

Shell
grep    '[0-9]\{4\}'   file    # BRE — braces escaped
grep -E '[0-9]{4}'     file    # ERE — natural
grep -P '\d{4}'        file    # PCRE — shorthand classes

\d does not exist in BRE or ERE. Use [0-9] or [[:digit:]] unless you have grep -P, which is absent on macOS and BSD.

sed and awk

sed -E gives you ERE and is worth using by default. GNU sed and BSD sed differ on in-place editing: sed -i on GNU, sed -i '' on macOS — a portability trap that silently creates backup files.

For extracting rather than testing, grep -o prints only the match and grep -P -o gives you PCRE with lookarounds, which covers most one-off extraction jobs without reaching for a script.

Quoting

Single-quote patterns passed to external commands so the shell does not expand $, * or backticks first. Inside [[ =~ ]] do the opposite and leave the pattern unquoted.

That inversion — quote for grep, do not quote for =~ — is the rule worth memorising, because both mistakes fail quietly rather than erroring.

Frequently asked questions

Why does my [[ =~ ]] pattern never match?

It is quoted. Bash then treats it as a literal string; leave the pattern unquoted or store it in a variable.

Why does \d not work in grep?

Basic and extended regex have no shorthand classes. Use [0-9] or [[:digit:]], or grep -P where available.

How do I capture groups in bash?

After a successful [[ =~ ]] match, groups are in the BASH_REMATCH array, with index 0 as the whole match.

Ready to try it?

Open the free browser-based Regex tester and apply what you just read — no sign-up, runs locally.

Open the Regex tester tool