Regular Expressions
Pattern Matching
String methods like find(), startswith(), and replace() work on fixed, known text. But many real-world problems involve text that follows a pattern rather than an exact string.
Does this string look like an email address? Extract all numbers from this sentence. Replace every date formatted as DD/MM/YYYY with YYYY-MM-DD. Find every word that starts with a capital letter.
These questions can't be answered with simple string methods. They require regular expressions — a language for describing patterns in text.
Python's re module provides the full regular expression engine.
Your First Pattern
re.search(pattern, string) scans the string for the first location where the pattern matches.
r"\d+" is the pattern:
\d— matches any digit character (0–9)+— one or more of the preceding element
The r prefix marks a raw string — backslashes are passed through literally, not interpreted as escape sequences. Always use raw strings for regex patterns.
Building Patterns: The Core Syntax
Character classes
| Pattern | Matches |
|---|---|
\d | Any digit 0–9 |
\w | Any word character: letters, digits, _ |
\s | Any whitespace: space, tab, newline |
\D | Any non-digit |
\W | Any non-word character |
\S | Any non-whitespace |
. | Any character except newline |
Quantifiers
| Quantifier | Meaning |
|---|---|
* | Zero or more |
+ | One or more |
? | Zero or one (optional) |
{n} | Exactly n times |
{n,m} | Between n and m times |
Anchors
| Anchor | Meaning |
|---|---|
^ | Start of string |
$ | End of string |
\b | Word boundary |
findall — All Matches at Once
re.search finds the first match. re.findall returns every match as a list:
\b is a word boundary — it matches the position between a word character and a non-word character. \b\w+at\b matches whole words ending in "at".
Groups — Extracting Parts of a Match
Parentheses in a pattern create groups — named portions of the match you can extract independently:
m.group(0) is the entire match. m.group(1), m.group(2), m.group(3) are the captured groups in order.
Named groups make patterns more readable:
(?P<name>...) defines a named group. re.finditer is like findall but returns match objects instead of strings — giving you access to groups and positions.
re.sub — Find and Replace by Pattern
re.sub(pattern, replacement, string) replaces every match. In the replacement string, \1, \2, \3 refer to captured groups — so \3-\2-\1 puts the year first, then month, then day.
With a function as the replacement:
When the replacement is a function, re.sub calls it with each match object and uses the return value as the replacement. Every number in the string is doubled.
Compiling Patterns
If you use the same pattern many times, compile it first with re.compile(). This parses the pattern once and reuses the result:
A compiled pattern object has the same methods as re itself — .search(), .findall(), .sub() — but avoids re-parsing the pattern string on every call.
re.split — Splitting by Pattern
[,;\s|]+ is a character class matching any of: comma, semicolon, whitespace, pipe — one or more in a row. re.split handles messy, inconsistent delimiters that str.split can't manage.
A Note on Complexity
Regular expressions are powerful and terse — sometimes dangerously so. A pattern that took ten minutes to write can be indecipherable six months later. Two practices help:
First, use re.VERBOSE to write readable patterns with comments:
Second, always test your patterns on real examples — regex errors are silent mismatches, not crashes.
What You Have Learned
Regular expressions describe text patterns precisely — enabling tasks that are impossible or extremely fragile with plain string methods.
The key ideas:
re.search— finds the first match;re.findall— returns all matchesre.finditer— returns match objects for each match (access groups and positions)re.sub— replaces by pattern; replacement can be a string with group references or a functionre.split— splits by pattern, handling complex or inconsistent delimitersre.compile— parses a pattern once for repeated use- Always use raw strings
r"..."for patterns - Core syntax:
\d,\w,\s,.,+,*,?,{n,m},^,$,\b - Groups
(...)extract parts of a match; named groups(?P<name>...)add clarity re.VERBOSElets you write and comment patterns across multiple lines
In the next lesson, you'll learn about concurrency — how Python handles multiple tasks at once, and how asyncio enables efficient asynchronous programming.