
Last checked by the TextEditor.com team
Which regex flavor this tester runs
A regular expression, or regex, is a small pattern that describes text. Each language reads patterns a little differently. This tester uses the JavaScript engine of your own browser, so a pattern acts here the same way it does in a web page or in Node.js.
PHP uses a library called PCRE, and Python has its own re module. Most signs mean the same in all three. These are the places where a pattern copied from one language breaks in another.
| What you want | JavaScript | Python | PCRE (PHP) |
|---|---|---|---|
| A named group | (?<name>...) | (?P<name>...) | (?<name>...) |
| A group in the replacement | $1 $<name> | \1 \g<name> | $1 \1 |
| Very start and end of the text | ^ and $ without the m flag | \A \z | \A \z |
Does $ match before a last line break? | No | Yes | Yes |
Does \w match é or ж? | No, also not with the u flag | Yes | Only in UCP mode |
| Flags inside the pattern | Only for a part, like (?i:abc), in browsers from 2025 on | (?i) at the start, or (?i:abc) | (?i) anywhere |
Atomic groups (?>...) and a++ | No | Yes, since Python 3.11 | Yes |
| Lookbehind length | Any length | Fixed length only | Limited |
The Python column was checked against the Python re documentation in November 2026. A pattern in a JavaScript file is written between slashes, like /\d+/g, so a slash inside it needs a backslash: \/. "Copy as code" in the tester does that for you.
Regex cheat sheet
Most patterns are built from the parts in this table. Letters and digits match themselves. The signs . * + ? ^ $ ( ) [ ] { } | \ / have a meaning, so put a backslash before one to find the sign itself.
| Pattern | Matches | Example |
|---|---|---|
| . | Any character except a line break | c.t finds cat, cut, c7t |
| \d \w \s | A digit, a word character (A to Z, a to z, 0 to 9, _), white space | \d\d finds 42 |
| \D \W \S | Anything except a digit, a word character, white space | \S+ finds each word |
| [abc] [a-z] | One character from the set or the range | gr[ae]y finds gray and grey |
| [^abc] | One character not in the set | [^,]+ finds the text between commas |
| ^ $ | Start and end of the text, or of each line with the m flag | ^# finds a # at the start |
| \b | A word edge | \bcat\b skips category |
| * + ? | The part before it zero or more times, one or more times, or optional | colou?r finds color and colour |
| {3} {2,} {2,4} | Exactly 3 times, 2 or more times, 2 to 4 times | \d{4} finds 2026 |
| a|b | a or b | cat|dog |
| (...) | A group that saves its match as $1, $2 | (\d+) kg |
| (?:...) | A group that does not save | (?:ab)+ finds ababab |
| (?<name>...) | A named group | (?<year>\d{4}) |
| \1 \k<name> | The same text a group found before | (\w)\1 finds the ll in hello |
| (?=...) (?!...) | Followed by, not followed by | \d+(?=%) finds the 15 in 15% |
| (?<=...) (?<!...) | After, not after | (?<=\$)\d+ finds the 40 in $40 |
| \p{L} | A letter in any alphabet (needs the u flag) | \p{L}+ finds Москва |
| \. \( \\ | The sign itself: a period, a bracket, a backslash | 3\.5 finds 3.5 |
Room 12, floor 3. Call 555-0142 before 9:30.
6 matches: 12, 3, 555, 0142, 9, 30
The MDN guide to regular expressions lists every part of the JavaScript syntax with more examples.
Greedy and lazy: .* or .*?
A repeat sign like + or * is greedy. It takes as much text as it can, and gives some back only when the rest of the pattern would fail. So <.+> runs from the first < to the very last > on the line.
A ? right after the repeat sign makes it lazy. It takes as little as it can and grows one character at a time until the rest matches.
<b>bold</b> and <i>italic</i>
1 match: <b>bold</b> and <i>italic</i>
<b>bold</b> and <i>italic</i>
4 matches: <b>, </b>, <i>, </i>
A set that leaves out the end sign often works better than lazy: <[^>]+> stops at the first > and never has to step back.
Groups, named groups and back references
Round brackets do two jobs. They hold parts together, so (ab)+ repeats the whole pair. They also save what they matched, so you can use it again. The tester lists each group under its match.
A name makes long patterns easier to read. (?<user>...) saves the text as "user", and $<user> puts it back in a replacement. If you only need the brackets to hold parts together, (?:...) does that without saving anything.
Mail [email protected] or [email protected]. This is is a test.
2 matches: [email protected] (user: ana, domain: example.com), [email protected] (user: ben.lee, domain: mail.co.uk)
\1 is a back reference: it must find the same text that group 1 found, so \b(\w+) \1\b finds a word typed twice. To run a replacement over a whole document, with undo and several rules in a row, use find and replace.
Lookahead and lookbehind
A lookaround checks the text next to a point without making it part of the match. (?=...) looks ahead and (?<=...) looks back. With ! in place of =, the text there must not match.
Prices: $40, $7.50, 25 EUR and 100 points. Save 15%.
2 matches: 40, 7.50
Prices: $40, $7.50, 25 EUR and 100 points. Save 15%.
1 match: 100
Prices: $40, $7.50, 25 EUR and 100 points. Save 15%.
5 matches: 40, 7, 50, 25, 100
In JavaScript a lookbehind can hold any pattern, also one with + or *. Python allows only a lookbehind of fixed length, so (?<=\$\s*) works here but fails in Python.
Flags
Flags change how the whole pattern works. In code they go after the last slash, like /cat/gi.
| Flag | Name | What it does |
|---|---|---|
| g | global | Finds every match, not only the first. Without it, replace changes only the first match. |
| i | ignore case | A and a count as the same letter. |
| m | multiline | ^ and $ match at the start and end of every line, not only of the whole text. |
| s | dot all | The dot matches line breaks too. |
| u | unicode | An emoji counts as one character, \p{...} works, and mistakes like \e become errors. |
| v | unicode sets | Everything u does, plus set math like [\p{L}--[a-z]]. Use u or v, not both. |
| y | sticky | Each match must start exactly where the last one ended. |
| d | indices | Gives the start and end of each group in the result. |
Tea for two coffee TEA time tea
No matches
The u flag matters for emoji. Without it, JavaScript sees 😀 as two halves, so ^.$ does not match it and 😀+ repeats only the second half.
Catastrophic backtracking

(a+)+ can try to match.Most patterns finish in a blink. A few take time that doubles with every extra character. The classic case is ^(a+)+$ on a row of a's that ends in a b. The engine tries every way to share the a's between the inner + and the outer +, and only then gives up. For 30 letters that is about half a billion ways.
aaaaaaaaaaaaaaaaaaaab
| Pattern | Time |
|---|---|
| ^(a+)+$ | Press Run |
| ^a+$ | Press Run |
Each test runs in a background worker that is stopped after 2 seconds, so this page stays usable. Add a few letters at a time and watch the first time double.
The tester at the top of this page works the same way. When a test takes more than 2 seconds it stops and shows "Pattern too slow". On a server there is no such stop, and a slow pattern can be used to block it, an attack called ReDoS.
To avoid it, never put a repeat inside a repeat when both can match the same text, as in (a+)+ or (\w+\s?)*. Make the choices in a|b unable to match the same text, and prefer a set like [^,]* over .*.
Common patterns and where they fail
These patterns cover everyday cases, and each has gaps. "Try it" loads one into the tester with a test text that shows where it fails.
| For | Pattern | Where it fails | Load |
|---|---|---|---|
| Email address | /[\w.+-]+@[\w-]+(?:\.[\w-]+)+/g | Finds most everyday addresses. It misses addresses with letters like é and quoted names, and it skips me@localhost, which works on some local networks. It does not check that the address is real. | |
| Web link | /https?:\/\/[^\s<>"]+/g | Takes a period or a bracket at the end of a sentence as part of the link. Misses links without http, like www.example.com. | |
| Date as 2026-11-07 | /\b(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])\b/g | Checks the month (01 to 12) and the day (01 to 31), but still takes 2026-02-31. Check real dates in your code. | |
| Number | /-?\d+(?:\.\d+)?/g | Reads 1,250.50 as two numbers and 1.2.3 as two. Decimal commas, like 3,5 in much of Europe, are not covered. | |
| Hex color | /#(?:[\da-f]{8}|[\da-f]{6}|[\da-f]{3,4})\b/gi | Also takes words like #fade or #bad that use only the letters a to f. | |
| Phone number (US) | /\(?\b\d{3}\)?[-. ]?\d{3}[-. ]?\d{4}\b/g | Only the ten digit North American form. Numbers from other countries have other lengths and groups. | |
| Doubled words | /\b(\w+)\s+\1\b/gi | Works only with the letters A to Z. With the i flag "The the" counts too, and the replacement keeps the first one. | |
| Spaces at line ends | /[ \t]+$/gm | Needs the m flag, or only the very end of the text is checked. Spaces at the start of lines stay. | |
| Double spaces | / {2,}/g | Only plain spaces. Tabs and no break spaces stay; [ \t\u00A0]{2,} catches those too. | |
| Empty lines | /^[ \t]*\r?\n/gm | An empty last line with no line break after it stays. | |
| HTML tags | /<[^>]+>/g | Breaks on a > inside an attribute or a comment. Never use it to make HTML safe; use a real HTML parser for that. | |
| IPv4 address | /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g | Rejects numbers over 255. In 1.2.3.4.5 it still finds 1.2.3.4, and it knows nothing of IPv6. | |
| Words in any alphabet | /\p{L}+(?:['’]\p{L}+)*/gu | Needs the u flag. Splits words at a hyphen, and Chinese or Japanese text with no spaces counts as one long word. |
No single pattern checks an email address or a date for sure. Use the pattern to find likely candidates, then check them in code: send a mail to the address, or let a date library read the date.