Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Regular Expressions with Python’s re Module

Learn regular-expression patterns, matching operations, capture groups, substitutions, splitting, flags, and safe limits with Python’s re module.

Levels: Intermediate ~30 min read

Intermediate

Regular expressions describe patterns in text. They are useful when a small, well-defined pattern can find, validate, extract, replace, or split text. They are not a substitute for a parser when the input has nested structure, and a complicated pattern can be harder to maintain than ordinary Python code.

Use raw strings for patterns

Regular-expression syntax uses backslashes, and Python string literals use backslashes too. Write most patterns as raw strings such as r"\d+" so Python does not consume the backslashes before the regular-expression engine sees them. Raw strings do not change the regular-expression language; they make the pattern easier to express as a Python string.

Interactive Runnable example
Edit

Ready to run.

Quick check

Why is a raw string usually the clearest way to write a regular-expression pattern containing backslashes?

import re
print(re.fullmatch(r"\d+", "2048") is not None)

Build patterns from small pieces

Ordinary characters match themselves. Character classes such as [A-Z] match one character from a set; ranges such as [0-9] are explicit, while \d matches a Unicode decimal digit by default for string patterns. The shortcuts \w and \s match word characters and whitespace. Quantifiers say how many repetitions are allowed: * means zero or more, + one or more, ? optional, and {m,n} a bounded count. Anchors such as ^, $, and word boundary \b describe positions rather than characters.

Interactive Runnable example
Edit

Ready to run.

Quick check

What does the quantifier {2,4} mean when it follows a pattern element?

import re
print(re.fullmatch(r"[A-Z]{2}\d{3}", "AB123") is not None)

Choose the operation that matches your question

Use search() to find the first match anywhere in the input. Use fullmatch() when the entire input must fit a format, such as a product code or a simple field value. Use finditer() when you need match objects and their positions; findall() is convenient when you only need the matched text or captured groups. Compile a reused pattern with re.compile() when that makes the code easier to read or reuses flags.

Python 3.15 API note: the current reference adds prefixmatch() for matching only at the start of a string and soft-deprecates match() in favor of that clearer name. The runnable examples in this archive were executed with Python 3.13.5, where prefixmatch() is not available, so they use search() and fullmatch() instead. Do not copy 3.15-only calls into a program that must support older Python versions.

Interactive Runnable example
Edit

Ready to run.

Quick check

Which operation should you normally choose when the whole input must match a pattern?

import re
print(re.fullmatch(r"[A-Z]{2}\d{3}", "ZX704") is not None)

Capture meaningful parts of a match

Parentheses capture a part of the match so you can retrieve it. Name a group with (?P<name>...) when the meaning matters more than its numeric position. A non-capturing group (?:...) groups alternatives or repetitions without changing the returned capture structure. Match objects expose group(), groups(), groupdict(), and span(). Backreferences can require a later part of the pattern to repeat an earlier capture; use them only when that relationship is part of the input format.

Interactive Runnable example
Edit

Ready to run.

Quick check

What does groupdict() return for a successful match with named capturing groups?

import re
match = re.fullmatch(r"(?P<left>\w+):(?P<right>\w+)", "red:blue")
print(match.groupdict())

Find, replace, and split text

finditer() yields one Match object at a time, so you can inspect matched text and positions without building a list of all results first. sub() creates a new string with matched text replaced; named or numbered captures can be reused in a replacement. split() separates text wherever the pattern matches. Capturing parentheses in the split pattern are included in the returned list, so prefer a non-capturing group when you only need structure.

Interactive Runnable example
Edit

Ready to run.

Quick check

Which function is designed to replace every non-overlapping match by default and return a new string?

import re
print(re.sub(r"\s+", "-", "red blue green"))

Flags, lookarounds, and sensible limits

Flags adjust matching without changing the main pattern: IGNORECASE handles case-insensitive matching, MULTILINE changes line-anchor behavior, DOTALL lets a dot include newlines, and VERBOSE allows readable patterns with comments. Lookahead checks what follows without consuming it; lookbehind checks what precedes it, and Python requires lookbehind patterns to have fixed length. Start with a readable pattern and test normal, boundary, and invalid inputs. Avoid nested ambiguous repetition on long untrusted text, and do not use a regular expression as a replacement for parsing nested syntax.

Interactive Runnable example
Edit

Ready to run.

Keep these decisions in mind

  • Prefer raw strings for patterns containing backslashes.
  • Use fullmatch() for whole-input checks, search() for a match anywhere, and finditer() when positions matter.
  • Use named groups when captured values have meaning, and keep patterns simpler than the data-processing problem requires.
Was this page helpful?

Mark this learning resource complete to track your learning progress.