Skip to content

All tools (41)

JSON 6
Time & Date 4
Encoding & Decoding 4
Generators 3
Text & Data 4
Logs & Debugging 1
Config & Infra 3
Security & Hashing 4
Color & Design 5
Numbers & Bits 3
Web & Markup 4

Nothing leaves the cave.

Nothing you paste ever leaves your device. There is no server to send it to.

How you can check →
DevToolsCave

    This tool runs entirely in your browser. Nothing you paste is uploaded.

    How you can check →

    grep -E regex tester — POSIX ERE and leftmost-longest matching, not leftmost-first

    Ships in: grep -E, egrep, sed -E / -r, awk

    Want to test your own pattern under POSIX ERE (grep -E, sed -E, awk)? Open the regex tester with this flavor already selected.

    Open the regex tester — POSIX ERE (grep -E, sed -E, awk) →

    grep -E, egrep, sed -E (or -r on GNU systems) and awk all compile against POSIX Extended Regular Expressions, and ERE differs from every Perl-family engine on this page — JavaScript, PCRE2, Python, Java, .NET, Go — in a way that is easy to state and easy to get wrong: matching is leftmost-longest, not leftmost-first.

    Concretely: (a|ab) against "ab" matches just "a" in every Perl-family engine, because alternation is tried left to right and the first branch that succeeds wins, full stop. Under POSIX ERE, the same pattern against the same input matches the full "ab", because POSIX requires the engine to find the overall longest match possible at the leftmost starting position, trying every alternative and every quantifier interpretation until it's certain nothing longer exists. This is not a minor edge case — it's the very first alternation most people write, and it is the exact place a browser-based tester that quietly runs everything through JavaScript's RegExp while showing a "POSIX ERE" label gets the answer wrong, with no indication anything is off.

    This tool implements a genuine second matching mode for the two POSIX flavors rather than approximating leftmost-longest behavior on top of a leftmost-first engine — continuing past the first accepting state at each starting position and keeping the longest run found, with capture assignment following POSIX's own outermost-first subexpression rule. Where our own golden-fixture testing against real grep and sed shows our capture-group assignment doesn't yet match theirs exactly on some constructs, this tool labels the capture columns as approximate rather than asserting a precision it hasn't verified — the overall match extent is still exact.

    GNU grep and sed extend bare POSIX ERE with a few Perl-style conveniences that aren't in the POSIX standard itself but are what actually ships on essentially every Linux system: \w, \W, \s and \S work as shorthand classes (though not \d — POSIX-flavored tools use [0-9] or the [[:digit:]] class instead), and \1 through \9 backreferences work against ERE's own unescaped parenthesized groups, which is worth knowing because RE2 — the engine underneath Go and ripgrep's default mode — deliberately has no backreferences at all, a completely different limitation for a completely different reason.

    Whether \w and friends match only ASCII or a broader Unicode-ish range under GNU grep/sed is locale-dependent in real POSIX tools, and this tool models the common modern default — a UTF-8 locale, where an accented letter counts as a word character — rather than the older LC_ALL=C ASCII-only behavior some scripts still assume. If your deployment target pins LC_ALL=C, test with that in mind: a pattern that matches an accented word here under the default locale model may not match identically in that stricter environment.

    One more GNU-specific accommodation worth knowing: an unescaped { that isn't part of a valid {n,m} interval is accepted as a literal character by GNU grep and sed, the same leniency JavaScript's legacy Annex-B grammar extends and Java flatly refuses — so a stray { in a pattern that happens to work under grep -E may fail to compile if the same source text is later run through Java's stricter parser.

    awk's regex support is the same POSIX ERE this page tests, with its own front door: gawk's match() and gsub() functions and its /pattern/ literal syntax all compile against ERE, so a pattern verified here transfers directly into an awk script's condition or field-matching logic without translation. This is a genuinely useful shortcut, since awk scripts are frequently the place a grep -E pattern ends up reused once the surrounding logic needs more than a single filter — testing the pattern once here covers both destinations.

    It's worth testing patterns meant for grep -E and sed -E on this page even when the eventual target is a shell script rather than an interactive terminal session, because the leftmost-longest rule doesn't announce itself as a bug when it disagrees with your expectation — a script using an alternation pattern will simply extract a different substring than the one a JavaScript-based tester led you to expect, with the script running to completion and producing plausible-looking, silently wrong output rather than an error anywhere in the pipeline.

    POSIX ERE (grep -E, sed -E, awk) quirks, at a glance

    The same facts this tool's engine implements and tests against — not a separate, unverified summary.

    • Matching is leftmost-LONGEST, not leftmost-first: (a|ab) against "ab" matches "ab" here, and matches just "a" in every Perl-family flavor (JS, PCRE2, Python, Java, .NET, Go).
    • No lookaround at all. Backreferences (\1..\9) DO work here as a GNU extension of grep -E/sed -E, referencing ERE's own unescaped ( ) groups — RE2 is the one that lacks backreferences entirely, by design.
    • GNU grep/sed accept { as a literal character when it is not part of a valid {n,m} — same accommodation as JavaScript's legacy grammar, for a different historical reason.

    A worked example: grep -E (ERE)

    Extracting a date like 2026-08-22[0-9]{4}-[0-9]{2}-[0-9]{2}.

    grep -E (ERE)
    grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' file

    This is the flavor the pattern was written for — leftmost-longest matching, with [[:digit:]]-style POSIX classes rather than \d/\w.

    Frequently asked questions

    Why does (a|ab) match "a" in JavaScript but "ab" under grep -E?
    Perl-family engines (JavaScript, PCRE2, Python, Java, .NET, Go) use leftmost-first matching: alternation is tried in order and the first branch that succeeds wins. POSIX ERE — what grep -E and sed -E actually run — requires leftmost-LONGEST matching instead, so it keeps searching until it's certain no longer match exists at that position.
    Does grep -E support \d for digits?
    Not natively — POSIX ERE has no \d. Use [0-9] or the POSIX class [[:digit:]] instead. GNU grep/sed do support \w, \W, \s and \S as extensions, just not \d.
    Does grep -E support backreferences?
    Yes — \1 through \9 work as a GNU extension against ERE's own unescaped ( ) groups. This is a different engine from Go's RE2 (which ripgrep also defaults to), which has no backreferences at all by design.
    Is grep -E's \w Unicode-aware?
    It's locale-dependent. Under a typical modern UTF-8 locale, an accented letter counts as a word character; under the older LC_ALL=C setting, matching reverts to ASCII-only. Test under the locale your deployment target actually uses.