Speed up millions of regex replacements in Python 3
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
When performing millions of regex replacements in Python, the key optimizations are: compile regex patterns once with re.compile(), combine multiple patterns into a single alternation pattern, use str.replace() or str.translate() instead of regex when possible, and process text in bulk rather than line-by-line. For pure word-to-word substitutions, building a single compiled regex from all words and using a dictionary lookup in the replacement function is orders of magnitude faster than looping through individual patterns.
The Slow Approach
This makes N full passes over the text, one per replacement. With 1000 patterns and a 10MB text, you scan 10GB of data.
Fix 1: Compile Patterns Once
re.compile() parses the regex once and returns a reusable pattern object. Without it, re.sub() parses the regex string on every call.
Fix 2: Single Combined Pattern with Dictionary Lookup
The fastest approach for many word replacements — combine all patterns into one regex:
This scans the text exactly once, regardless of how many replacement patterns exist.
With Word Boundaries
Fix 3: Use str.replace() for Literal Strings
If patterns are literal strings (no regex metacharacters), str.replace() is faster:
Fix 4: Use str.translate() for Character-Level Replacements
Fix 5: Process in Chunks with multiprocessing
Benchmark Comparison
Common Pitfalls
- Not compiling regex patterns when reusing them: Each
re.sub(pattern_str, ...)call parses the regex string into an internal automaton. In a loop processing millions of strings, this parsing overhead accumulates significantly. Always usere.compile()outside the loop. - Building a combined pattern without
re.escape(): If replacement keys contain regex metacharacters (.,*,+,(), the combined pattern breaks or matches unintended text. Always escape keys withre.escape()when building the alternation. - Not sorting patterns by length in the alternation: Regex alternation
a|abmatchesabefore tryingab, causing partial matches. Sort patterns longest-first soabis tried beforea. - Using regex when
str.replace()suffices: For literal string replacements (no wildcards, no word boundaries),str.replace()is 3-5x faster thanre.sub()because it avoids regex engine overhead entirely. - Processing text line-by-line when bulk processing is possible: Reading a file line-by-line and applying regex to each line incurs function call overhead per line. Read the entire file into a single string (if it fits in memory) and apply the regex once.
Summary
- Combine all patterns into a single
re.compile("|".join(...))for a single-pass replacement - Use a dictionary lookup function as the replacement argument to
re.sub() - Compile patterns with
re.compile()and reuse the compiled object - Use
str.replace()for literal strings andstr.translate()for character-level replacements - For massive text, split into chunks and use
multiprocessing.Poolfor parallel processing
Related reading
- Speed up Spring Boot startup time
- Speed up Spring Boot startup time
- Speed up the initial TensorFlow startup
- Speeding up a search for best binary matching number
- Speeding up pairing of strings into objects in Python
- speedup TFLite inference in python with multiprocessing pool
- Speeding up cassandra queries if nodes are offline
- Speeding up simulations

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.