Regex Ninja 忍
the pattern-matching dojo
Slash symbols flying
Need the right regex
to catch the right strings.
Write a pattern. Watch it fly through the field below. Slice every string that belongs - and only the strings that belong. Very addictive.
Enter the dojoPractice Arena
Slice the correct strings
Level 0 — Recruit
0/5 katas sliced clean
0 / 120 XP to next rank
Digits Only
Slice strings that are made of digits, and only digits — nothing else sneaks through.
Sensei says
A regex that takes three minutes to write and thirty seconds to read is a good regex.
Belt progression
- White Belt
- Yellow Belt
- Green Belt
- Brown Belt
- Black Belt
Scrolls of the Dojo
Skills every ninja must know
Anchors
^ $ \b \B
Pin a match to the start, end, or edge of a word.
Character classes
[abc] [^abc] \d \w \s
Match one character from a set — or its opposite.
Quantifiers
* + ? {n,m}
Say how many times a piece may repeat.
Greedy vs. lazy
.* vs .*?
Greedy grabs as much as possible; lazy grabs as little as possible.
Groups & alternation
( ) | (?: )
Bundle pieces together, or offer several options.
Flags
i g m s u
Change how the whole pattern behaves — case, lines, unicode.
Backreferences
\1 (?<name> )
Refer back to something you already captured.
Lookaround
(?=) (?!) (?<=) (?<!)
Check what’s nearby without consuming it.
The Dojo Code
Do’s and don’ts
Do
- ·Anchor patterns with ^ and $ when the whole string must match — not just part of it.
- ·Escape special characters ( . * + ? ( ) [ ] { } | ^ $ \ ) whenever you mean them literally.
- ·Use non-capturing groups (?:...) when you don’t actually need the captured value.
- ·Test against edge cases: empty strings, whitespace, unicode, and very long input.
- ·Name your capture groups (?<label>...) once a pattern gets more than two groups.
- ·Reach for a visual tester before you ship a pattern into production code.
Don’t
- ·Don’t use regex to parse full HTML or XML — reach for a real parser instead.
- ·Don’t nest quantifiers carelessly, e.g. (a+)+ — that’s how catastrophic backtracking is born.
- ·Don’t forget case sensitivity — add the i flag or silently miss half your matches.
- ·Don’t reach for a hungry .* when a precise character class already does the job.
- ·Don’t skip testing — a pattern that "looks right" can still misfire on the one input that matters.
- ·Don’t confuse greedy and lazy quantifiers when matching nested delimiters like quotes or tags.
Keep In Mind
Quick reference
| Token | Meaning |
|---|---|
| . | Any character except a line break |
| \d \D | A digit — or anything but a digit |
| \w \W | A word character — or anything but one |
| \s \S | Whitespace — or anything but whitespace |
| ^ $ | Start of string/line — end of string/line |
| \b \B | A word boundary — or the absence of one |
| * + ? | Zero-or-more, one-or-more, zero-or-one |
| {n,m} | Between n and m repetitions |
| ( ) (?: ) | Capturing group — non-capturing group |
| | | Alternation: this OR that |
| [abc] [^abc] | One of these characters — none of these |
| (?=) (?!) | Followed by / not followed by (lookahead) |
| (?<=) (?<!) | Preceded by / not preceded by (lookbehind) |
| \1 (?<n>)\k<n> | Backreference to a captured group |
Before you commit a pattern
- Does it reject everything it should reject, not just accept what it should accept?
- Does it survive an empty string without throwing?
- Would a teammate understand it in under a minute?
- Have you checked it against unicode or multi-byte input if that’s in scope?
Performance, briefly
Catastrophic backtracking happens when nested or overlapping quantifiers force the engine to try exponentially many ways to fail. Prefer specific character classes, atomic-style grouping where your engine supports it, and possessive quantifiers or lookaheads to cut off dead ends early.