Regular Expressions: a Basic Guide
The 2006 guide to regular expressions, with a new chapter: one badly written regex can stall a server.
1. Practical Foundations: Validating a Web Form
Regular expressions (regex) are an indispensable tool for software developers: they describe string patterns exhibiting formal regularity, collapsing dozens of procedural validations into a single concise expression.
In the practical tutorial «Espressioni Regolari (Guida Base)», the practical baseline was a ubiquitous web application task: validating user form inputs:
- First Name: single word, alphabetic letters only (including accented characters), optional:
^[a-zA-Zàòèéùì]*$ - Last Name: one or more words, letters, spaces, and apostrophes, required:
^[a-zA-Zàòèéùì' ]+$ - Email: alphanumeric prefix with periods/underscores,
@symbol, domain name, and 2-to-4 letter TLD:^[a-zA-Z0-9_.]+@[a-zA-Z0-9-]+\.[a-zA-Z]{2,4}$ - Phone Number: dialing code and subscriber number separated by hyphen:
^[0-9]+-[0-9]+$
2. The Developer Toolbox: Classes, Ranges, Quantifiers, and Anchors
Constructing reliable expressions relies on core building blocks:
- Character classes
[...]and range operator-: square brackets match a single occurrence of any character within the set. The hyphen specifies ordered ranges:[a-z]for lowercase,[0-9]for digits, or composite sets like[a-fA-F0-9]for hexadecimal values. - Repetition quantifiers: asterisk
*matches zero or more occurrences (admitting empty sets for optional inputs); plus+mandates one or more occurrences; curly brackets{min,max}define exact thresholds, such as[0-9]{3,4}-[0-9]{7}. - Escape character
\: prefixing metacharacters (such as\.,\-, or\/) disables their operational function, evaluating them as literals. - Anchors
^and$:^enforces matching from the string start and$at the end. Without anchors,[0-9]+matches partially insideabc123xyz, invalidating the integrity check.
3. The Greedy Trap: Greedy Quantifiers vs. Negated Classes
Repetition quantifiers are greedy by default: they consume the longest possible character sequence matching the pattern.
Applying <.+> to an HTML string:
<HTML><HEAD><TITLE>REGULAR EXPRESSIONS</TITLE></HEAD><BODY></BODY></HTML>fails to match individual tags: it consumes everything from the first < to the final > across the line, swallowing the entire markup structure.
Two distinct remedies exist with fundamentally different runtime profiles:
- Reluctant quantifier
<.+?>: halts at the first>, but incurs step-by-step backtracking. - Negated character class
<[^<>]+>: explicitly states that any character except<or>may appear. The state machine proceeds linearly without ambiguity.
Similarly, isolating sentences ending in a period is written as [^.]+, leveraging character class negation via ^ inside brackets.
If a routine merely strips whitespace or checks string prefixes, avoid regular expressions entirely: native string functions (includes,indexOf,replaceAll) are an order of magnitude faster and carry zero algorithmic risk.
4. Production Outages: ReDoS and Catastrophic Backtracking
Most modern programming languages (PHP, JavaScript, Python) rely on Non-deterministic Finite Automata (NFA) regex engines. When patterns contain nested quantifiers or overlapping alternations—such as ^(a+)+$ or (a|a+)+$—the engine explores permutations recursively.
On valid input like aaaaa, evaluation is instantaneous. But when presented with non-matching strings—such as thirty a characters followed by an exclamation mark aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!—the NFA engine explores every branch before failing.
Computational steps explode exponentially in O(2n). On an input of merely 30 characters, evaluation exceeds a billion operations, pinning a CPU core at 100% for minutes.
This vulnerability, known as Regular Expression Denial of Service (ReDoS), is not theoretical: on July 2, 2019, a single regex rule with catastrophic backtracking (.*.*=.*) deployed to Cloudflare's WAF pinned edge server CPUs globally, causing a 27-minute worldwide outage.
5. The AI Era: Decision Models, Data Extraction, and the Math Under the Hood
Until recently, early language models exhibited a notorious limitation: they could not reliably count how many times the letter 'r' appeared in the word strawberry. The cause was structural: neural networks do not ingest individual characters, but process subword tokens. For decades, engineers wrote sprawling, brittle regular expressions laden with lookarounds and complex groups to scrape and extract entities from messy unstructured documents.
With modern reasoning architectures and decision models, this landscape changed completely. Contemporary models grasp semantic context, correct typos, normalize messy records, and rewrite chaotic text with an adaptability no handcrafted pattern could ever match. On the surface, regular expressions appear to have been rendered obsolete.
The architectural irony is that AI has not eliminated regular expressions: it uses them under the hood to optimize its most critical foundational tasks:
- Tokenization and pre-processing: tokenizers powering leading models (such as BPE in
tiktoken) split raw character streams using compiled regular expressions before any tensor mathematics take place. - Structured Outputs and constrained decoding: when requiring an LLM to emit strictly valid JSON conforming to a schema (via engines like Outlines, vLLM, or provider Structured Outputs APIs), the runtime compiles the regex schema into a Deterministic Finite Automaton (DFA). At every autoregressive generation step, the DFA applies a logit mask, setting the probability of any syntax-violating token to zero. It is regular language theory and automata math that enforce strict determinism onto a probabilistic machine.
This highlights a crucial principle for engineering leadership: understanding computer science fundamentals enables asking AI the right questions.
An inexperienced operator delegates the brute-force extraction to the model: feeding a 50MB log file into the context window and prompting the LLM to rewrite and extract fields token by token. The outcome is severe latency, exorbitant token bills, context window exhaustion, and unpredictable hallucinations.
An engineer grounded in formal languages and algorithmic complexity takes the opposite approach: prompt the reasoning model on a minimal sample to diagnose the invariant structure, directing it to synthesize a deterministic mathematical solution—a linear DFA, native string operations, or a backtracking-safe regex. That compiled routine then processes millions of records locally in memory at zero marginal compute cost, in linear time and with predictable behavior. AI thus becomes a precision synthesizer of deterministic code, rather than a costly probabilistic engine kept permanently online for basic formatting checks.