9.10 Regular Expressions with Strings
The re module -- match() vs search(), findall()/finditer(), sub()/split(), pattern compilation, capture groups and named groups, and lookahead/lookbehind assertions.
What Is Regex?
A regular expression is a mini-language for describing text patterns — used for validation, extraction, and bulk find/replace. Python’s built-in re module implements it, and it’s the production-grade alternative to the naive character-by-character search shown in 9.9 String Algorithms for anything beyond simple literal matching.
A named-group pattern for 2026-07-13: match.group("year") → "2026".
re.match() vs re.search()
match() only succeeds if the pattern matches starting at position 0; search() scans the whole string for the first match anywhere. Use match() to validate that an entire string starts a certain way, search() to find something buried inside larger text.
>>> import re
>>> re.match(r"\d+", "123abc") # anchored at the START of the string
<re.Match object; span=(0, 3), match='123'>
>>> re.search(r"\d+", "abc123def") # finds the FIRST match anywhere
<re.Match object; span=(3, 6), match='123'>
re.findall() / re.finditer()
findall() collects every match into a list of strings; finditer() gives the same matches lazily as Match objects, useful when each match’s position is also needed.
>>> re.findall(r"\d+", "a1 b22 c333")
['1', '22', '333']
re.sub() / re.split()
sub() replaces every match with a given string — the regex equivalent of str.replace() but pattern-based. split() breaks a string apart wherever the pattern matches, useful when the separator itself is irregular (variable amounts of whitespace, for example).
>>> re.sub(r"\s+", " ", "too many spaces")
'too many spaces'
>>> re.split(r",\s*", "a, b,c, d")
['a', 'b', 'c', 'd']
Pattern Compilation
Compiling a pattern once and reusing it for repeated matching (e.g. inside a loop over thousands of log lines) avoids re-parsing the pattern every call.
>>> pattern = re.compile(r"\d+")
>>> pattern.findall("a1 b22")
['1', '22']
Groups and Named Groups
Parentheses in a pattern capture matched sub-text for later use; groups() returns all captures as a tuple in order. (?P<name>...) attaches a label so a group can be retrieved by name instead of position — far more readable with many groups, and less fragile to reorder.
>>> m = re.match(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "2026-07-13")
>>> m.group("year"), m.group("month"), m.group("day")
('2026', '07', '13')
Lookahead and Lookbehind
A lookahead (?=...) matches a position only if followed by a given pattern, without including that pattern in the match — useful for a value only when it has a specific unit or suffix nearby. A lookbehind (?<=...) is the mirror image.
>>> re.findall(r"\d+(?=px)", "10px 20em 30px") # digits followed by 'px'
['10', '30']
>>> re.findall(r"(?<=\$)\d+", "$50 and 30") # digits preceded by '$'
['50']
Quick Interview Answer
“
match()anchors at position 0;search()finds a match anywhere.findall()returns matched strings;finditer()returns lazyMatchobjects with position info.sub()andsplit()are the pattern-based equivalents ofstr.replace()andstr.split(). Capture groups pull structured sub-fields out of a match — named groups ((?P<name>...)) make multi-group patterns readable instead of positional and fragile. Lookahead/lookbehind assert that a pattern exists nearby without consuming it into the match itself. Compiling a pattern once withre.compile()avoids re-parsing it on every call inside a hot loop.”
Common Mistakes
- Using
match()whensearch()is actually needed —match()silently returnsNonefor anything not anchored at position 0, which is easy to misdiagnose as “the pattern is wrong.” - Forgetting parentheses in a pattern create a capturing group even when capture isn’t the intent — use
(?:...)for a non-capturing group if grouping is only needed for precedence. - Re-compiling the same pattern inside a loop instead of compiling it once outside — wasteful when processing many lines, as in log parsing (see 9.12 Strings in DevOps and AWS).
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form