Free DevOps Tool

Regex Tester & Builder

Test and debug regular expressions with live match highlighting, capture group inspector, replace preview, and instant code snippets in JavaScript, Python, Go, Java & PHP. Includes a pattern library for common DevOps patterns.

Live HighlightingCapture GroupsReplace PreviewJS · Python · Go · Java · PHPPattern LibraryCheatsheet
//g
Test String
2 matches
#1contact@devopslesson.compos 8, 32
#2hello@example.orgpos 36, 53
Pattern Builder

Click any pattern to load it into the tester

How to use the regex tester

Six steps. Matching runs in your browser as you type, so nothing you paste is uploaded.

  1. Enter the pattern and set the flags

    Type the expression in the bar at the top. g finds every match rather than the first, i ignores case, m makes ^ and $ match at each line rather than only at the ends of the input, and s lets . match a newline. Most log work wants g and m.

  2. Paste the text you are matching against

    Use real input rather than a shortened example. Matches highlight as you type, so a pattern that works on a tidy sample and fails on a real log line shows the difference immediately, which is usually a trailing space or a field that is sometimes empty.

  3. Check the capture groups, not just the match

    The Groups tab shows what each pair of brackets captured. If you are extracting a field rather than testing for one, this is the tab that matters, and it is where you find out that a greedy .* swallowed everything up to the last delimiter instead of the first.

  4. Start from a built pattern when one fits

    The panel on the right has ready patterns for email, IPv4, semver, a Docker image reference and others. Loading one and editing it is faster and less error-prone than writing a URL or IP pattern from scratch, which almost nobody gets right first time.

  5. Test the replacement before you run it

    The Replace tab takes a substitution string where $1 and $2 are the capture groups, and previews the result. Do this before running sed -i over a directory, because that command has no undo.

  6. Copy the snippet for the language you are using

    The Code Snippet tab emits working code for JavaScript, Python, Go, Java and PHP with the pattern and flags already set. It handles the escaping, which is where a correct pattern usually breaks on its way into source.

Regex in DevOps tools, and where the flavours differ

A pattern is not portable. The same expression means different things to grep, sed, Go and Prometheus, and the differences usually change what matches rather than producing an error you would notice. This is what to check before copying a pattern out of here.

grep

Basic regular expressions by default, which is a smaller language than you expect.

The characters +, ?, |, ( and { are literal in BRE and must be backslash-escaped to act as operators. Use grep -E for extended syntax where they work normally, or grep -P for Perl syntax if you need \d, \s and lookarounds. Plain grep supports none of those shorthands.

sed

Basic regular expressions like grep, with sed -E for extended.

Backreferences in the replacement are \1, not $1, which is the opposite of nearly every language, and & means the whole match so a literal ampersand has to be escaped. GNU and BSD also differ on in-place editing: GNU takes sed -i, macOS needs an explicit empty suffix after it.

awk

Extended regular expressions, used in patterns and in match().

Awk has no capture groups in the usual sense. Gawk provides match() with a third argument to get them; POSIX awk makes you pull substrings out with RSTART and RLENGTH. If you need captures, that is often the point to switch to a real language.

JavaScript

The flavour this tester runs, and what you get in Node and in the browser.

Lookbehind exists but only in reasonably modern engines. There is no \A or \z, and $ matches before a trailing newline. A pattern written here works in Node unchanged, which is not true of one you copy into grep.

Python re

Close to PCRE, with named groups written as (?P<name>...).

Write patterns as raw strings, otherwise Python consumes the backslashes before the regex engine ever sees them. And re.match anchors at the start of the string while re.search does not, which is a separate mistake people make repeatedly.

Go regexp

RE2, which guarantees linear-time matching.

RE2 has no backreferences and no lookahead or lookbehind at all, by design: those are the features that allow catastrophic backtracking. A pattern that works everywhere else can simply fail to compile in Go. The same applies to anything else built on RE2.

Prometheus and Grafana

RE2 as well, and label matchers are anchored for you.

A matcher written as job=~"api" behaves as ^api$, so it does not match api-gateway. Write api.* when you want a prefix. This catches nearly everyone once, usually while an alert quietly matches nothing.

Greedy versus lazy quantifiers

* and + take as much as they can; *? and +? take as little.

On a line holding two quoted strings, the pattern ".*" matches from the first quote to the last rather than the first pair. Use ".*?" or, better, "[^"]*", which is both clearer and faster because it cannot backtrack.

Anchors with multiline input

^ and $ mean start and end of input until the m flag makes them mean start and end of line.

Forgetting m when matching a log file gives you one match at the very top instead of one per line. The opposite mistake, leaving m on when validating a single value, lets a multi-line input pass a check it should have failed.

Catastrophic backtracking

Nested quantifiers such as (a+)+ can take exponential time on input that nearly matches.

This is an availability bug rather than a performance nit: a regex over user input has taken production services down. Avoid nesting a quantifier inside a quantified group, prefer a negated character class to .*, and use RE2 semantics where the engine offers them.

Regex questions people actually ask

What regex flavour does this tester use?

JavaScript, because it runs in your browser. That is the same engine as Node, so a pattern that works here works there unchanged. For grep, sed, Go or Prometheus, check the reference below before copying: those flavours differ in ways that silently change what a pattern matches rather than producing an error.

Why does my regex work here but not in grep?

Plain grep uses basic regular expressions, where +, ?, | and ( are literal characters and the \d, \s and \w shorthands do not exist at all. Use grep -E for extended syntax, or grep -P for a Perl-compatible flavour close to what this tester runs.

What is the difference between greedy and lazy matching?

A greedy quantifier takes as much text as it can and gives back only what it must; a lazy one (*?, +?) takes as little as possible. Against <a><b>, the pattern <.*> matches the whole string while <.*?> matches just <a>. Where you can, a negated class such as <[^>]*> beats either, because it cannot backtrack.

How do I use a capture group in a replacement?

It depends on the tool, and this trips people up constantly. JavaScript, Python and most languages use $1 or \1 in the replacement string. sed uses \1, and & for the whole match. Test the substitution in the Replace tab before running sed -i, which rewrites files in place with no undo.

Is regex the right tool for parsing logs?

For pulling a field out of a line, yes, and it is usually the fastest thing available. For anything with nested or quoted structure, such as JSON logs, use a parser instead: jq for JSON, or your log system own field extraction. A regex that handles quoting correctly is long, slow and easy to get subtly wrong.

Is my pattern or test text sent anywhere?

No. Matching happens in your browser, which is why it updates as you type. Nothing is uploaded or stored, so pasting a real log line with hostnames or IP addresses in it is safe.

Where you will use this

Learn Bash & Linux: Step by Step

Regex powers Bash scripting, log analysis, and CI/CD pipelines. Master it with our free Linux tutorials.