C.W.K.
Stream
Lesson 09 of 10 · published

When NOT to Use Regex

~10 min · limits, anti-patterns, html-parsing

Level 0Pattern-Curious
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

The famous Stack Overflow answer

If you ask Stack Overflow how to parse HTML with regex, you'll get a famous unhinged-but-correct answer that ends with the line "He comes." The lesson it's teaching is real: regex is not a parser.

What regex genuinely cannot do

Nested structures. Matching balanced parentheses to arbitrary depth is not a regular language. ((a)) vs (((a))) requires counting, and pure regex can't count. Some PCRE engines added recursion ((?R)) to fake it, but you've left the regex theory behind.

HTML / XML / Markdown / JSON / YAML / source code. All of these have nested structure. Use a parser. Python has html.parser, lxml, json, yaml. JavaScript has DOMParser, JSON.parse. Every language has a real parser for every real format.

Semantic validation. Regex can check shape, not meaning. \d{4} matches "9999" — but is 9999 a valid year? You need code for that.

Anything Unicode-deep. Right-to-left scripts, emoji ZWJ sequences, combining characters, locale-specific casing. Regex *can* touch this with \p{...} and Unicode flags, but it's almost always the wrong tool.

The smell test

If your pattern is over 100 characters, has more than 4 nested groups, or you're using lookbehind to fake context tracking — stop. You're trying to parse, not match. Reach for the right tool: an HTML parser, a YAML library, a hand-written tokenizer, an AST walker.

Regex is shape detection. The moment your problem becomes structural, hand it off.

Code

Wrong tool, right tool·python
# WRONG — trying to extract <a href> from HTML with regex
import re
links = re.findall(r'<a\s+href="([^"]+)"', html)
# Breaks on: single quotes, attributes in any order, multi-line tags,
# escaped quotes, comments, CDATA... the list is endless.

# RIGHT — use a real HTML parser
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
links = [a['href'] for a in soup.find_all('a', href=True)]
# Handles every edge case correctly. Forever.

External links

Exercise

Audit one regex in your codebase that's over 80 characters. Ask: is it doing shape detection (good) or structural parsing (bad)? If it's parsing, sketch what a real parser would look like instead. You don't have to rewrite it today — just notice the line.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.