Log file, 4,000 lines, one task: pull every 2024-05-01-style date plus the order number on the same line. My first pattern .*date.* matched the whole file as one blob. My second, with the right flags and a named group, returned 37 clean rows in one pass. Two thirds of regex pain is flags, not patterns — g/i/m/s change what the same characters mean. This guide teaches flags first, capture groups second, and the catastrophic patterns that freeze tabs.
Part of the developer toolkit guide. Test live in the regex tester (worker-isolated, per-flag control). Validate JSON logs with the JSON formatter first.
Flags g/i/m/s: same pattern, four meanings
| Flag | Does | Example win |
|---|---|---|
| g (global) | All matches, not just first | \d+ pulls every number (“Order 42” → 42, plus the rest) |
| i (insensitive) | Case-blind | error matches ERROR, Error, eRrOr in logs |
| m (multiline) | ^/$ per line | 4000-line logs: match per-line timestamps |
| s (dotAll) | . crosses newlines | Multi-line stack traces as one match |
Debug sequence for a dead pattern: toggle g (only-first vs all?), then i (case?), then m (anchors per line?). Nine of ten “broken regex” reports I review are a missing flag, not a wrong pattern.
Capture groups: named beats numbered
(\d{4})-(\d{2})-(\d{2}) captures year/month/day as groups 1/2/3 — until someone adds a group in front and every index shifts. Named groups ((?<year>\d{4})-(?<month>\d{2})) survive refactoring because names don't renumber. Non-capturing (?:…) groups without capturing (keeps indexes stable, slight speed win). Backreferences (\1) match repeats — (\w+) \1 finds doubled words like “the the”. Practice set: extract order + date pairs from the sample log in the tester with one pattern and two named groups.
Catastrophic patterns (and the worker that saves you)
(a+)+$ on a long non-matching string doesn't fail — it explodes, trying exponentially many paths (ReDoS). Nested quantifiers, overlapping alternations and greedy .* before a required suffix are the classic triggers. Defenses in order: prefer lazy quantifiers or explicit character classes, anchor patterns, cap input size — and test in a runner that isolates execution. Our tester runs patterns in a Web Worker with timeouts and flags potentially-catastrophic shapes before running, so the worst case is a warning, never a frozen tab. If your pattern needs a paragraph of explanation, split it into two patterns and a line of code instead.
General guidance only. For security-critical validation (emails, URLs, auth), prefer purpose-built parsers plus allowlists — regex alone under-validates.