/flags/sed/sed-e-extended-regex
sed -E: use extended regular expressions (same as sed -r)
- tool
- sed
- command
- sed
- flag
- -E, -r, --regexp-extended
- default
- off (basic regular expressions, BRE)
sed -E makes sed read patterns as extended regular expressions (ERE), so +, ?, |, ( ) and {n,m} are operators without backslashes. Without it, sed uses basic regular expressions (BRE), where those characters are literal and groups must be written \(...\). -r and --regexp-extended are GNU synonyms for -E; use -E, which also works with BSD sed on macOS.
Same substitution in BRE and ERE
echo 'v1.22.3' | sed 's/\([0-9]*\)\.\([0-9]*\)/\2.\1/'
echo 'v1.22.3' | sed -E 's/([0-9]+)\.([0-9]+)/\2.\1/'
echo '--- + is literal without -E'
echo 'aaa+b' | sed 's/a+/X/'
echo 'aaa+b' | sed -E 's/a+/X/'
echo '--- alternation'
echo 'a|b' | sed 's/a|b/Z/'
echo 'a|b' | sed -E 's/a|b/Z/g'Output
v22.1.3 v22.1.3 --- + is literal without -E aaXb X+b --- alternation Z Z|Z
In basic mode a+ matched the two characters a+, so only the last a and the plus sign were replaced; with -E it matched aaa. The same happens with |: in BRE it is the pipe character.
What changes with -E
| Meaning | BRE (default) | ERE (-E) |
|---|---|---|
| Group | \( \) | ( ) |
| One or more | \+ (GNU only) | + |
| Zero or one | \? (GNU only) | ? |
| Alternation | \| (GNU only) | | |
| Repeat count | \{2,4\} | {2,4} |
| Literal parenthesis | ( | \( |
| Literal plus sign | + | \+ |
| Backreference in replacement | \1 | \1 |
The flip side of -E is that characters which were literal now need escaping. A literal parenthesis in ERE must be \(, otherwise sed reports an error:
echo '(x)' | sed -E 's/(/[/'Output · exit 1
sed: -e expression #1, char 6: Unmatched ( or \(
GNU sed prints Unmatched ( or \( with the position in the expression. Escape it as s/\(/[/ in ERE, or drop -E for that command.
Typical uses
printf '2026-10-24 ERROR disk full\n2026-10-24 INFO ok\n' > app.log
sed -E 's/^([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/' app.log
sed -nE '/ (ERROR|WARN) /p' app.logOutput
24.10.2026 ERROR disk full 24.10.2026 INFO ok 2026-10-24 ERROR disk full
Reformatting dates, extracting version numbers and filtering on several keywords are all shorter in ERE. Combined with -n and the p flag, sed -nE works like a grep that can also rewrite.
Pitfalls
- Option order.
-Eaffects every expression in the call, including those from-eand-f. - Shorthands are GNU only.
\ddoes not exist in sed;\w,\sand\bare GNU extensions. Use[0-9],[[:space:]]and[[:alnum:]_]for portable scripts. - Combined flags.
sed -Eiworks on GNU sed; on macOS-ineeds a suffix argument, see GNU vs BSD sed. - No lazy quantifiers.
.*?is not supported in either mode; use a negated class such as[^"]*.
FAQ
What is the difference between sed -E and sed -r?
None in GNU sed: -r is the original GNU spelling and -E was added for compatibility with BSD sed. macOS sed has always used -E and older versions do not accept -r, so -E is the portable choice. POSIX added -E to sed in its 2024 edition.
Why does my sed regex with + or | not match anything?
Without -E, sed uses basic regular expressions, where +, ?, | and ( ) are literal characters. GNU sed accepts \+, \? and \| as operators in basic mode, but the portable fix is to add -E.
Do backreferences like \1 still work with -E?
Yes. Groups are written (...) instead of \(...\), and the replacement still refers to them as \1 to \9. Inside the pattern, backreferences in an ERE are a GNU extension.