Signs you should stop
Some patterns are fighting the wrong battle. Signs your regex has crossed the line:
- Pattern is over 100 characters and growing. You're parsing, not matching shapes.
- You need to track context across the input. "Inside a quoted string, ignore X" — that's lexer work, not regex.
- You need to count or balance. Nested parens, balanced quotes — non-regular by definition.
- You need recursion. If
(?R)is on the table, you've outgrown regex. - You're chaining 3+ regex passes. Probably want a parser.
- The pattern is fragile to formatting changes. One stray space breaks it.
- You can't read it out loud. Production-ready regex should be readable.
What to reach for instead
Parsers for nested structures:
- HTML / XML → BeautifulSoup, lxml, DOMParser
- JSON → json.loads, JSON.parse
- YAML → PyYAML, js-yaml
- Source code → AST (Python
ast, JS Babel parser) - Custom DSLs → write a real lexer/parser (PLY, Lark, nom, ANTLR)
Specialized libraries for known formats:
- URLs →
urllib.parse,new URL() - Dates →
datetime, dateutil, date-fns - Phone → libphonenumber
- IPs →
ipaddress, net.IP - Versions → packaging.version, semver
The reframing
Reaching for the right tool isn't admitting defeat — it's senior judgment. Beginners reach for regex for everything because it's the hammer they know. Experienced engineers know which problems regex actually solves and which it just postpones.