The tester

The tester needs JavaScript, which is switched off or blocked in this browser. The patterns on the other pages of this topic can still be tried with the short scripts shown there.

How to use it

  1. Pick one of the examples, or type your own pattern between the slashes. Write the pattern as you would inside /…/ in JavaScript: no quotes, and a single backslash (\d, not \\d).
  2. Paste or type test text: lines that should match and lines that should not. The near misses find most bugs, as Testing, Debugging and Readability explains.
  3. Switch flags on and off and watch what changes. The Flags and Modes page explains each one.
  4. To try a replacement, tick Replace each match with and type the replacement text. An empty replacement deletes the matches.
  5. When the pattern works, Copy gives it as a JavaScript literal such as /\bINC-\d{5}\b/g. For another language, see Regex in Python, JavaScript and PHP for how to write it there, and test it in that language too.

Reading the results

  • Highlights in the text show each match; matches that follow each other alternate between two underline styles so you can see where one ends and the next begins. A match of zero characters (for example from ^ or \b alone) cannot be highlighted, but it is listed.
  • Matches lists every match with its position, counted in UTF-16 code units from 0, the way JavaScript counts string positions.
  • Groups: each capturing group is listed by number, and a named group (?<name>…) also by its name. "(did not take part)" means the group sits in a branch that was not used, which is different from a group that matched an empty string. See Groups, Captures and Backreferences.
  • Replacement uses JavaScript's replacement syntax: $1 for group 1, $<name> for a named group, $& for the whole match and $$ for a dollar sign. Without the g flag only the first match is replaced. Python and PHP write group references differently; see Search and Replace.

One engine: JavaScript

The tester uses the regex engine of the browser you are reading this in, so it answers the question "what does this pattern do in JavaScript?" Most of the basics in this topic are the same everywhere, but not all of it. Things that work elsewhere and fail or behave differently here:

  • Python's named group syntax (?P<name>…) is an error; JavaScript writes (?<name>…).
  • Possessive quantifiers such as a++ and atomic groups (?>…) from PCRE (PHP) and newer Python versions are errors in JavaScript.
  • \A and \Z do not exist. Without the u flag, \A quietly matches the letter "A" instead of the start of the text; with u it is reported as an error. That is one reason to switch on u: it makes JavaScript reject escapes it does not know.
  • POSIX classes such as [[:digit:]] from grep and sed are not an error but mean something else: a character class of the characters [ : d i g t followed by a literal ].
  • Newer features depend on the browser version: inline modifiers such as (?i:…) arrived in ES2025 and give "Invalid group" in older browsers.

The Regex Flavors page compares the engines in detail. For a pattern that will run in Python, PHP or grep, use the tester to explore and then run your test lines in the real tool.

Safe to use

Everything happens in your browser: the pattern and the text are never sent to a server, and nothing is stored when you leave the page. That makes this tester different from online testers, where pasted text leaves your control. Even so, practice with invented lines rather than real logs with customer data, the same advice as in Online regex testers.

A pattern with nested quantifiers can take minutes, hours or longer on a line of a few dozen characters. To keep the page responsive, the tester matches in a background worker and stops it after one second. The Catastrophic backtracking example shows this on purpose: ^(a+)+$ against a line of as ending in !. Replace the pattern with ^a+$ and the answer is instant. Why that happens, and how to write patterns that cannot explode, is explained in Performance and Catastrophic Backtracking. (In a browser that cannot start a background worker, the tester runs in the page itself, limits the text to 20,000 characters and leaves out that example.)

Things to try

  • Incident numbers: remove the \b at the end and see what happens to the six-digit typo. Then switch on i: is inc-20418 a valid ticket number in your system?
  • ISO dates: change the replacement to $1/$2/$3, then make the groups named and use $<year> in the replacement.
  • IPv4: compare it with the short pattern \b\d{1,3}(?:\.\d{1,3}){3}\b and see which lines it wrongly accepts.
  • Log lines: switch off m and see why the anchored pattern no longer matches any line.
  • Doubled words: switch off i and see which pair is no longer found.
  • Trailing whitespace: the result removes the invisible spaces and tabs at the ends of the lines; switch off m and only the last line is cleaned.