Python
regular expressions
regex
string matching
programming

How can I find all matches to a regular expression in Python?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Python, the usual way to find every regex match is to use the re module. The right function depends on what you need back: strings, match objects, capture groups, or overlapping matches. Once you understand the return shape of each function, the task becomes predictable instead of trial and error.

Use re.findall For The Simplest Case

If you only need the matched text, re.findall is usually the fastest path.

python
1import re
2
3text = "Order A-12, order B-34, order C-56"
4pattern = r"[A-Z]-\d+"
5
6matches = re.findall(pattern, text)
7print(matches)

This returns:

python
['A-12', 'B-34', 'C-56']

findall scans left to right and returns non-overlapping matches. That makes it ideal for extraction tasks where positions and metadata are not needed.

Use re.finditer When You Need Positions

If you need start and end indexes, use re.finditer. It yields match objects instead of plain strings.

python
1import re
2
3text = "alpha 42 beta 99"
4pattern = r"\d+"
5
6for match in re.finditer(pattern, text):
7    print(match.group(), match.start(), match.end())

This is better than findall when you want to highlight matches in a UI, replace selected ranges, or build a parser.

Capturing Groups Change findall Output

One common source of confusion is that findall changes its return value when the pattern contains capturing groups.

python
1import re
2
3text = "cat:10 dog:20 bird:30"
4pattern = r"([a-z]+):(\d+)"
5
6matches = re.findall(pattern, text)
7print(matches)

The result is:

python
[('cat', '10'), ('dog', '20'), ('bird', '30')]

That behavior is useful once you know it, but surprising if you expected full matched strings. If you want the whole match and grouped parts, finditer is often clearer.

Compile The Pattern For Reuse

If the same expression is used repeatedly, compile it once.

python
1import re
2
3regex = re.compile(r"\b[a-z]{3}\b", re.IGNORECASE)
4
5print(regex.findall("One two three four six ten"))
6print(regex.findall("red blue green"))

Compiled patterns improve readability and avoid repeating flags in every call.

Handle Overlapping Matches With Lookahead

findall does not return overlapping matches. If you need overlaps, use a zero-width lookahead.

python
1import re
2
3text = "ababa"
4pattern = r"(?=(aba))"
5
6matches = re.findall(pattern, text)
7print(matches)

This returns two matches for aba, starting at different positions. Without the lookahead, Python would return only the first non-overlapping match.

Flags Matter More Than People Expect

Many "why did regex miss this?" bugs are really flag problems.

python
1import re
2
3text = "Error\nwarning\nERROR"
4pattern = r"error"
5
6print(re.findall(pattern, text))
7print(re.findall(pattern, text, flags=re.IGNORECASE))

You may also need re.MULTILINE for line-anchored patterns or re.DOTALL if . should cross newline boundaries.

A Practical Extraction Example

Here is a small example that extracts emails from text and preserves where they occurred.

python
1import re
2
3text = "Contact [email protected] or [email protected] for help."
4pattern = r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}"
5
6for match in re.finditer(pattern, text):
7    print({
8        "email": match.group(),
9        "start": match.start(),
10        "end": match.end(),
11    })

This is the sort of task where finditer is usually better than findall, because position data is part of the result you care about.

Common Pitfalls

  • Using findall and forgetting that capturing groups change the return type.
  • Expecting overlapping matches without using a lookahead-based pattern.
  • Using findall when you really need positions and match metadata.
  • Forgetting flags such as re.IGNORECASE or re.MULTILINE.
  • Writing patterns that are too broad and then blaming the matching function instead of the regex itself.

Summary

  • Use re.findall when you want all matched strings quickly.
  • Use re.finditer when you need match objects and positions.
  • Remember that capturing groups change what findall returns.
  • Use compiled patterns when the same regex appears in multiple places.
  • For overlapping matches, switch to a lookahead-based pattern instead of expecting findall to do it automatically.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.