FIRST CH TOOLS / 31 Regex Tester
Regex Tester
Type a pattern and some text, and every match is highlighted where it sits. The contents of each capture group, the position of every match and the result of a replacement are all on the same screen, and the g, i, m, s, u and y flags are one click away. JavaScript (ECMAScript) flavour — this page calls your browser's own RegExp.
It matches as you type
Replacing is a preview only — the text above is left alone. \n and \t are read as escapes.
Neither the pattern nor the text ever leaves your browser (matching runs on this page's own RegExp). You can also call it straight from a URL: /en/regex/?pattern=%5Cd%2B&flags=g&text=a1b22c333 or /en/regex/?pattern=…&flags=gi&replace=%5B%241%5D
JavaScript regex cheat sheet
| . | Any character except a line break (add the s flag to include them) |
|---|---|
| \d \D | A digit (0-9) / anything else. Full-width 123 does not match |
| \w \W | Letters, digits and underscore ([A-Za-z0-9_]) / anything else. Non-Latin scripts do not match |
| \s \S | Whitespace (space, tab, line break, ideographic space) / anything else |
| [abc] | Any one of these. Ranges work too: [a-z0-9] |
| [^abc] | Any one character except these (a leading ^ negates the class) |
| \p{…} | Needs the u flag. \p{L} letters, \p{N} numbers, \p{sc=Han} kanji, \p{sc=Hiragana} hiragana |
| \t \n \r | Tab, line feed, carriage return |
| \\ \. \* | Put a backslash in front to mean the symbol itself (. * + ? ^ $ ( ) [ ] { } | \) |
| * | Zero or more of what came before. ab* also matches a bare a |
|---|---|
| + | One or more |
| ? | Zero or one (optional) |
| {3} | Exactly three. {2,} is two or more, {2,4} is two to four |
| *? +? ?? | Lazy. <.+> swallows the whole line; <.+?> stops at the first tag |
| ^ $ | Start and end of the text — or of every line with the m flag |
|---|---|
| \b \B | A word boundary / anything but. \bcat\b skips concatenate. "Word" means \w, so this is Latin-only |
| (?=…) | Lookahead: a position followed by … (the … itself is not part of the match) |
| (?!…) | Negative lookahead: a position not followed by … |
| (?<=…) | Lookbehind: a position preceded by … |
| (?<!…) | Negative lookbehind: a position not preceded by … |
| (…) | Capture group — you get the contents back ($1, $2 when replacing) |
|---|---|
| (?:…) | A group that captures nothing. Cheaper when you only need the grouping |
| (?<name>…) | Named group. $<name> when replacing, m.groups.name in code |
| \1 \k<name> | Back-reference: the same text that group actually matched, again |
| a|b | Either one. Use brackets to bound it: ^(a|b)$ |
| $& | The whole match |
|---|---|
| $1 $2 | The first and second capture group |
| $<name> | A named group |
| $` $' | Everything before / after the match |
| $$ | A literal $ |
| g | global — do not stop at the first hit. Also what makes replace touch every match |
|---|---|
| i | ignoreCase — treat upper and lower case as the same |
| m | multiline — ^ and $ match at every line |
| s | dotAll — . matches line breaks too |
| u | unicode — unlocks \p{…} and treats emoji as single characters |
| v | unicodeSets — a superset of u with set subtraction like [\p{L}--[a-z]] (cannot be combined with u) |
| y | sticky — match only at lastIndex, used for tokenisers |
| d | hasIndices — group positions. This page turns it on for you |
".*" eats to the end of the line
<b>A</b> and <b>B</b> <b>.*</b> → matches the whole thing (greedy) <b>.*?</b> → matches only <b>A</b> (lazy)
Quantifiers take as much as they can by default. If the same character appears again past your intended end, the engine swallows it and then backtracks. Add ? to go lazy, or write a character class that excludes the terminator, like [^<]*. The second form never backtracks, so it is both faster and safer.
A quantifier inside a quantifier can hang
^(a+)+$ ← dangerous (explodes on text that almost matches) try "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" and watch the combinations grow ^a+$ ← same meaning, safe
When one quantifier wraps another, a failed match makes the engine try every way of splitting the text, so the time grows exponentially with length (ReDoS). In code that validates user input, that is a denial of service waiting to happen. This page gives up collecting matches after one second and flags patterns shaped like this. Note that backtracking inside a single match attempt cannot be interrupted, so an extreme pattern can still make the page stop responding for a while — there is no way to interrupt a JavaScript regex, which is exactly what makes the same bug serious on a server.
"\d" and "\w" only know ASCII
\w+ → does not match 東京
[\p{L}]+ → matches it, with the u flag on
[ぁ-んァ-ヶ一-龠]+ → ranges work, but always miss something
\w, \d and \b are defined over ASCII. For other scripts, turn on the u flag and use \p{sc=Han}, \p{sc=Hiragana} or \p{L}, which cover rare characters and variants as well. Note too that full-width digits (123) never match \d.
lastIndex survives between calls
const re = /a/g;
re.test('abc'); // true (lastIndex becomes 1)
re.test('abc'); // false (no "a" after position 1)
A regex object with g or y remembers where it stopped. That is why a shared test() or exec() returns false every other call. Reset re.lastIndex = 0 outside the loop, or simply leave g off patterns you only use for validation (String.matchAll and replaceAll handle this for you).
Other languages spell some things differently
Not in JavaScript: \A \z (use ^ and $)
(?>…) atomic groups, a++ possessive quantifiers
/x extended mode (ignore whitespace and comments)
In JavaScript: (?<=…) lookbehind, \p{…} with the u flag, v-flag set operations
This page calls your browser's own RegExp, so results follow the JavaScript (ECMAScript) spec exactly. Patterns written for PHP's preg_* (PCRE) or Python's re may fail here on syntax JavaScript never had. The flip side: whatever works here works unchanged in the browser and in Node.js.
Do not try to validate email addresses perfectly
[\w.+-]+@[\w-]+\.[\w.-]+ ← enough to catch a typo
A regex that follows RFC 5322 to the letter runs to hundreds of characters and nobody can maintain it. Keep form validation at "there is an @ and something domain-shaped after it", and let a confirmation email decide whether the address really works. The same goes for URLs, phone numbers and postal addresses.
Do not parse HTML with regular expressions
pulling <a href="…">…</a> out with a regex → nesting, > inside attributes and comments all break it
use document.querySelectorAll('a') or DOMParser instead
HTML nests, and a regular language cannot describe nesting. One-off edits and machine-generated markup are fine in practice, but anything written by someone else deserves a real parser. Same story for JSON and CSV: if a parser exists, it will be more reliable.
How to Use
- Enter a patternWrite the expression between the slashes. If you pasted it from code as /…/gi, one button strips the slashes and picks up the flags. You can also start from a common pattern (email address, URL, date and so on).
- Paste your textMatches light up on the right, and the position and capture groups of each one are listed below. Flip a flag and everything updates on the spot.
- Check the replacementPut $1 or $<name> in the replacement field to preview the result, then copy it straight out.
About This Tool
This is for checking that a regular expression does what you think it does. Type a pattern and some text, and matches are highlighted in place. Adjacent matches alternate colour, so you can tell where one ends and the next begins. Zero-length matches (a lone \b or a bare lookahead) are drawn as a thin bar, which means you can see the "nothing is highlighted but the count keeps rising" case instead of guessing at it.
Every capture group, one match at a time. Alongside the matched text you get the value of each (…) group and where in the text it came from. Named groups such as (?<year>…) are labelled with their name, and groups that did not participate are shown as "(no match)" rather than left blank — handy when you are working out which branch of an | alternation fired.
Try a replacement without touching the original. The replacement field understands $&, $1 and $<name>. Since a single-line field cannot hold a line break, \n and \t are read as escapes. Result to input moves the replaced text back into the input box, so you can stack several passes and see where you end up.
It points out the usual traps. When a missing g flag limits you to one hit, when line breaks in the text make . or ^ / $ behave differently from what you expect, or when a nested quantifier like (a+)+ (the classic cause of ReDoS) shows up, the reason is spelled out below the results. Collecting matches is abandoned after one second (backtracking within a single attempt cannot be interrupted, so an extreme pattern may still stall the page briefly).
JavaScript (ECMAScript) flavour. Because this page hands your pattern to the browser's own RegExp, anything that works here can be pasted straight into JavaScript or Node.js. Conversely, syntax that only exists in PCRE (PHP) or Python — \A, atomic groups, possessive quantifiers, extended mode — will not work. Turn on the u flag and \p{sc=Han} and friends let you target scripts by name.
Nothing you type leaves your device. To compare before and after, use the Text & Code Diff Checker; to pull a URL apart, the URL Parameter Editor; and to make strings worth testing against, the Test Data Generator.
Other Tools
- 01Batch Image → WebPWebP Converter
- 02White Background RemoverWhite BG Remover
- 03WCAG Contrast CheckerContrast Checker
- 04Character CounterCharacter Counter
- 05llms.txt Generatorllms.txt Generator
- 06JSON-LD GeneratorJSON-LD Generator
- 07Markdown → PDFMD → PDF
- 08OGP Meta Tag WizardOGP Wizard
- 09Favicon GeneratorFavicon Generator
- 10TikTok PublisherTikTok Publisher
- 11Encoding & Line Ending ConverterEncoding Converter
- 12Batch Image → AVIF + pictureAVIF Converter
- 13Test Data GeneratorTest Data Generator
- 14Marp Markdown → SlidesMarp Slides
- 15Text & Code Diff CheckerDiff Checker
- 16Cron Explainer & Next RunsCron Explainer
- 17Base64 & Data URI EncoderBase64 & Data URI
- 18URL Parameter Editor & UTM BuilderURL Parameters
- 19HTML Entity Escape & UnescapeHTML Escape
- 20JSON ⇄ YAML ConverterJSON ⇄ YAML
- 21PX ⇄ REM / EM ConverterPX ⇄ REM / EM 単位変換
- 22Color Converter & AlphaColorコード変換&アルファ透過
- 23MD5 / SHA-256 Hash Generatorハッシュ生成
- 24JWT Decoder & Expiry CheckerJWTデコーダー&有効期限チェッカー
- 25User-Agent ParserUser-Agent解析&デバイス判定
- 26UUID & ULID GeneratorUUID (v4) & ULID 一括生成
- 27Aspect Ratio Calculatorアスペクト比計算&サイズ算出
- 28Markdown Table GeneratorMarkdownテーブル整形&CSV/TSV変換
- 29SQL Query FormatterSQL Formatter
- 30QR Code GeneratorQR Code Generator
- 32Unix Timestamp ConverterUNIXタイムスタンプ⇄日時変換
- 33New Tab Memo — Chrome Extension新規タブメモ帳 Chrome拡張
- 34Image Resizer & Cropper画像リサイズ&クロップ
- 35EXIF Viewer & RemoverEXIF情報の確認&除去
- 36robots.txt Generatorrobots.txt ジェネレーター
- 37Password Generator安全なパスワード生成
- 38Case Converter文字列ケース変換