jamuny.editor

Regex Tester

Flags

0 matches

Write a pattern, see every match highlighted in your text immediately, and inspect the capture groups for each one, numbered and named. A replacement field previews the result before you commit to it. Patterns run against a time limit, so a pattern that backtracks catastrophically reports the problem instead of freezing the page.

What "local-first" means

Most online text tools send whatever you paste to a server, run the work there, and send a result back. Your words sit in someone else's logs, backups and databases, and you have to trust a privacy policy.

Local-first means the opposite: the whole tool is downloaded to your browser and runs on your own device. Nothing you type is transmitted anywhere: not to us, not to anyone. There is no server that could receive it, which is a stronger guarantee than a promise not to look.

Three consequences worth knowing:

You do not have to take that on trust. Open your browser's developer tools, watch the network panel, and type: nothing appears in it.The network's verify page walks through the same check on every Jamuny tool.

How to use it

  1. Write a pattern. Type the expression without surrounding slashes. Flags have their own checkboxes.
  2. Paste your test text. Every match highlights immediately as you type, so you can narrow a pattern by watching what stops matching.
  3. Inspect the groups. Each match lists its capture groups, numbered and named, so you can see exactly what a group caught.
  4. Preview a replacement. The replace field shows the result before you commit, with $1 and $<name> expanded.

Worked example

Pulling the parts out of an ISO date

Input
Pattern:  (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Text:     Released 2026-08-05 and patched 2026-08-19
Output
Match 1: 2026-08-05   year=2026  month=08  day=05
Match 2: 2026-08-19   year=2026  month=08  day=19

Which regex dialect you are testing against

JavaScript's, as implemented by the browser you are using right now. That is the point: if you are writing a pattern for JavaScript, testing it in a PHP or Python engine can pass here and fail in production, or the reverse.

Lookbehind assertions, named capture groups and Unicode property escapes all work in current browsers. Constructs that exist only in PCRE (recursive patterns, possessive quantifiers, the \K reset) do not, because JavaScript has never had them.

Why a pattern times out

Some patterns take exponential time on input that nearly matches. The classic shape is a quantifier inside another quantifier, like (a+)+$, run against a long string of a characters ending in something else. The engine tries every way of splitting the input before concluding there is no match, and the number of ways doubles with each character.

That is catastrophic backtracking, and on a live server it is a denial-of-service vulnerability, not just a slow page. Matching here runs in a background worker that is stopped after one second, so the tab stays responsive and you get told which pattern did it.

The usual fix is to remove the ambiguity about where one repetition ends and the next begins, often by making the inner quantifier more specific, or by anchoring the pattern so failure is detected early.

Capture groups in replacements

Numbered groups expand as $1, $2 and so on, counting opening parentheses from the left. Named groups, written (?<name>...), expand as $<name>, which survives someone later inserting a group in the middle and renumbering everything.

A literal dollar sign in a replacement is written $$. Getting that wrong is a common way to produce output that looks almost right and silently drops characters.

Questions

Which regex dialect is this?

JavaScript's, as implemented by your own browser. Lookbehind, named capture groups, and Unicode property escapes all work in current browsers. Perl or PCRE-only constructs will not.

Why did my pattern time out?

Some patterns, typically nested quantifiers like (a+)+ against a long non-matching string, take exponential time. Matching runs in a background worker that is stopped after one second, so the page stays responsive instead of hanging.

Can I use capture groups in the replacement?

Yes. Use $1, $2 for numbered groups and $<name> for named ones. The replacement preview updates live, and nothing is applied to your text until you choose to apply it.