A regular expression is not a description of a string. It is a tiny search program, and the engine runs it: at each starting position it walks the pattern left to right, and every quantifier and every | is a decision it can come back and revise. Nearly everything that surprises people falls out of that one fact — why greedy and lazy return different answers, why the order of alternatives changes the result, why one pattern is instant and its lookalike hangs a server for two seconds. Learn the search and the syntax becomes a table you look up. Learn only the syntax and every failure looks like a new mystery.
Each chapter opens with the short version. Tap one to read the detail.
How a match actually happens
~2 min
A match is a span found inside the subject, not a verdict on the whole string. With no anchor the engine tries position 0, then 1, then 2, and the first start that works wins. A pattern that can match nothing succeeds at position 0, consuming nothing.
The backtracking model, and why first beats longest
~2 min
The engine searches depth-first and rewinds. Every quantifier and every | is a decision point it can revisit, so a pattern is a tree of paths rather than a formula. The consequence that catches everyone: the winner is the first path that succeeds, never the longest available.
Saying which characters count
~2 min
A bracketed class consumes exactly one character, so [cat] is never the word "cat". Ranges are code-point ranges, a negated class still consumes a character, and the shorthand escapes mean different things in different engines — \w is plain Latin in JavaScript and Unicode-aware in Python.
Repetition, and who gives characters back
~2 min
A quantifier binds to the single atom before it, takes as much as it can, then hands characters back one at a time until the rest of the pattern fits. Adding ? makes it start minimal and grow instead. A possessive *+ hands nothing back — and JavaScript has no possessive form.
Anchors and word boundaries
~2 min
^ and $ assert a position and consume nothing. The m flag moves them to every line break and changes nothing about .. \b is the seam between a word character and a non-word character, so it inherits whatever that particular engine thinks a word character is.
Groups, names and backreferences
~2 min
Groups are numbered by their opening parenthesis, index 0 is the whole match, and a group in an untaken branch reads as undefined or None, never as an empty string. Names are an alias over that numbering — and their syntax is one of the sharpest flavour splits there is.
Testing without consuming
~2 min
A lookaround tests the text at the current position and then puts the cursor back, adding a condition without eating anything. That is what lets several independent rules apply at one spot, and what makes "a line that does not contain this word" expressible at all.
Catastrophic backtracking, measured
~2 min
One shape — a quantifier wrapped around something already quantified and ambiguous — turns a pattern exponential. The dangerous input is the one that almost matches, since only a failure forces every path. Measured below: 22 as take 28 ms, 28 take 1.7 seconds.
Flags, and the regex object that remembers
~2 min
Flags change how a pattern is parsed or how the methods iterate, rarely both. m moves the anchors and does nothing to .; s does the opposite. And in JavaScript a g or y regex is a stateful object that remembers where its last match ended.
Getting the answer out
~2 min
Choose the call by what you need back: a boolean, an index, one match with its captures, or every match. Two costly surprises — JavaScript's match with g throws the captures away, and Python's findall returns groups rather than whole matches once the pattern has any.
The same pattern in three engines
~2 min
"What does this pattern match?" has no answer until you name the engine. Three families dominate — JavaScript, Python's re, and the Perl-compatible family built on the PCRE2 library — and they disagree about anchors, word characters, lookbehind width, and whole feature sets.
When not to reach for a regex
~2 min
A regex is the right tool for a small, flat, well-defined shape and the wrong one for anything nested or quoted. Write down what the pattern must reject before you write the pattern, and never build one by pasting user input straight into it.
Written by Keentune. We are not affiliated with or endorsed by the organizations whose documentation informs this guide, and any linked sources belong to their respective owners.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.