The first move: paste it into regex101
Whatever the bug, your first action should be: copy the pattern, copy the input, paste both into regex101.com with the right flavor selected. The explanation pane decomposes the pattern; the match panel shows what hit and what didn't.
Half of regex bugs are invisible until you see them visualized.
Debug flag in Python
re.compile(pattern, re.DEBUG) prints the compiled state machine. Useful for understanding how the engine actually parses your pattern.
The narrowing technique
When a pattern "doesn't match what it should," cut it in half:
- Take the first half of the pattern, test against the input. Does it match?
- Take the second half. Does the input have what it expects?
- Find the boundary where the failure starts.
This bisection finds the issue faster than staring at the whole pattern.
Logging captures
If the issue is "matches but captures wrong stuff," print every group:
m = pattern.search(text)
if m:
print(m.group(0)) # whole match
print(m.groups()) # numbered groups
print(m.groupdict()) # named groups
print(m.span()) # position
Common bug signatures
- "Returns None": probably anchoring or wrong escape (raw string?).
- "Matches too much": greedy vs lazy, or missing word boundaries.
- "Matches too little": missing optional pieces, wrong character class.
- "Hangs": catastrophic backtracking. Look for nested quantifiers.
- "Works in tester, fails in code": flavor mismatch or string escape issue.