This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →sed regex tester — POSIX BRE, where ( ) and { } are literal and \( \) \{ \} do the work
Ships in: grep (no -E), sed (no -E/-r)
Want to test your own pattern under POSIX BRE (grep, sed default)? Open the regex tester with this flavor already selected.
Open the regex tester — POSIX BRE (grep, sed default) →A bare sed 's/pattern/replacement/' — no -E, no -r — and a bare grep 'pattern' file both run POSIX Basic Regular Expressions, and BRE is the one flavor on this page where the grouping and quantifier metacharacters are inverted from literally every other engine here. In every Perl-family flavor and even in POSIX ERE, ( ) create a group and { } write a quantifier. In BRE, ( ) and { } are plain literal characters, and it's the backslashed forms — \( \), \{ \} — that create a group or an interval quantifier instead.
This single inversion is the most common reason a sed one-liner "doesn't work" the first time someone writes it: a pattern like (abc){2} written with ERE or Perl instincts matches the literal eight-character string "(abc){2}" under bare sed, not two repetitions of "abc" grouped together. The working BRE equivalent is \(abc\)\{2\}. It looks unfamiliar the first several times, and it is exactly why the -E flag (or -r on GNU sed, both work identically on modern GNU systems) exists — it switches sed to ERE, where the more familiar unescaped ( ) and { } apply.
| for alternation, + for one-or-more, and ? for zero-or-one are not real metacharacters in strict POSIX BRE at all — a bare | in a BRE pattern matches a literal pipe character. GNU grep and sed extend BRE with \|, \+ and \? as GNU-specific extensions carrying the ERE meaning, and that extended behavior is what this flavor models, because it's what actually ships and what nearly every BRE pattern anyone writes today assumes. A strictly conforming, non-GNU sed (some BSD and embedded systems) will not accept \| at all, which is worth checking if portability beyond Linux matters for a given script.
Backreferences work here exactly as in ERE: \1 through \9 reference the \( \) groups in source order, which makes BRE — despite its unfamiliar bracket-escaping — strictly more capable in one specific way than RE2 (the engine behind Go and ripgrep's default mode), which has no backreferences at all. A pattern like \(.\)\1 (match any character immediately followed by itself) is valid, working BRE syntax.
Matching itself follows the same POSIX leftmost-longest rule as ERE, not the leftmost-first rule every Perl-family engine on this page uses — the same (a|ab)-against-"ab" divergence covered in the grep -E guide applies here too, just spelled \(a\|ab\) once you're using the GNU \| extension instead of bare |.
The s command's own delimiter is a separate, easy-to-forget escaping layer on top of the pattern itself: s/pattern/replacement/ uses / as the field delimiter, so a literal / inside the pattern or replacement needs \/ — or, more cleanly, sed lets you pick a different delimiter entirely, s|pattern|replacement| being the common choice when the pattern is a file path full of slashes. That delimiter choice is orthogonal to BRE-versus-ERE, but it's the second most common reason a sed one-liner someone pasted from a forum doesn't run as written against a path-like input.
The replacement side of an s/// command has its own small syntax, separate from BRE itself: & stands for the whole match (not $& the way JavaScript or .NET spell it), and GNU sed adds \U, \L and \E to upper-case, lower-case, or stop transforming the text that follows, entirely absent from the POSIX standard but present on essentially every Linux system's sed. A replacement of \U&\E upper-cases whatever the pattern matched — a small, GNU-only convenience that has no equivalent at all in strict POSIX BRE or ERE's replacement rules, and is worth checking for before relying on it in a script meant to run on BSD or a minimal container image's sed.
Matching capture behavior under leftmost-longest carries into the s command too: because BRE's captures are POSIX subexpressions rather than Perl-style ordered alternatives, a backreference-heavy substitution can extract a different, longer piece of text than the leftmost-first intuition from JavaScript or Python would predict for the identical-looking pattern — one more reason to verify a nontrivial sed substitution here, against this tool's genuine POSIX matching mode, before trusting it against production data.
POSIX BRE (grep, sed default) quirks, at a glance
The same facts this tool's engine implements and tests against — not a separate, unverified summary.
- Grouping and quantifier metacharacters are inverted from every other flavor here: ( ) { } are LITERAL, and \( \) \{ \} are what create a group or an interval quantifier.
- | and + and ? are not metacharacters in strict POSIX BRE at all — GNU grep/sed accept \| \+ \? as GNU extensions with the ERE meaning, which is what this flavor models, since that is what actually ships.
- \1 through \9 backreference the BRE groups \( \) in source order — unlike ERE, which has no backreferences at all.
- This is the flavor a bare `grep 'pattern' file` or `sed 's/pattern/.../' file` actually runs — -E/-r is required to get ERE instead.
A worked example: sed -E
Extracting a date like 2026-08-22 — [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.
sed -E 's/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/replacement/g' file
-E is the portable spelling for ERE mode on both GNU and BSD/macOS sed; -r is a GNU-only synonym that BSD/macOS sed does not accept.
Frequently asked questions
- Why does (abc){2} not work in plain sed?
- In POSIX BRE — what sed uses without -E or -r — ( ) and { } are literal characters, not grouping or quantifier syntax. The working equivalent is \(abc\)\{2\}, with the backslashed forms doing what the unescaped ones do in every other flavor here.
- Does sed support | for alternation?
- Not in strict POSIX BRE — a bare | matches a literal pipe. GNU sed extends BRE with \| as a GNU-specific extension carrying the ERE meaning; non-GNU sed (some BSD systems) may not accept it at all.
- What's the difference between sed and sed -E?
- Plain sed runs POSIX BRE, where ( ) { } are literal and \( \) \{ \} create groups and quantifiers. sed -E (or -r on GNU) switches to POSIX ERE, where the unescaped ( ) { } work the more familiar way and | + ? become real metacharacters without backslashes.
- Can I use backreferences in sed's default mode?
- Yes — \1 through \9 reference the \( \) groups in source order in both BRE and ERE. This is one specific capability BRE has that RE2 (Go's regexp, and ripgrep's default mode) lacks entirely.
Other flavors
ECMAScript RegExp, exactly as your browser or Node runs it
the engine behind PHP's preg_* and most Apache/nginx rewrite rules
re module rules, Unicode-by-default, 3.11+ possessive quantifiers
java.util.regex rules for Java, Kotlin, Scala and Android
System.Text.RegularExpressions rules, including the group-numbering quirk
RE2 rules, including why lookaround and backreferences don't compile
POSIX ERE and leftmost-longest matching, not leftmost-first