Python Regular Expressions
Learn to use Python's re module for powerful pattern matching, searching, extracting, and substituting text.
Regex Basics and the re Module
A regular expression (regex) is a pattern that describes a set of strings. Python's re module provides functions to search, match, and manipulate text using these patterns.
import re # re.search() - find first match anywhere in string result = re.search(r"\d+", "Order #4523 confirmed") print(result.group()) # 4523 # re.match() - match only at the START of string result = re.match(r"Hello", "Hello, World!") print(result.group()) # Hello # re.findall() - find ALL matches, return as list emails = "Contact [email protected] or [email protected]" found = re.findall(r"\w+@\w+\.\w+", emails) print(found) # ['[email protected]', '[email protected]'] # re.sub() - search and replace text = "My phone is 0412-345-678" cleaned = re.sub(r"-", "", text) print(cleaned) # My phone is 0412345678
Always use raw strings (r"...") for regex patterns to avoid issues with backslash escaping.
Common Regex Patterns
Regex uses special characters called metacharacters to build patterns. Here are the most important ones for Year 12.
| Pattern | Meaning | Example Match |
|---|---|---|
| \d | Any digit (0-9) | "7" in "Year 7" |
| \w | Word character (a-z, A-Z, 0-9, _) | "Hello" |
| \s | Whitespace (space, tab, newline) | " " in "hello world" |
| . | Any character except newline | "a", "1", "!" |
| + | One or more of previous | \d+ matches "123" |
| * | Zero or more of previous | a* matches "", "aaa" |
| ? | Zero or one of previous | colou?r matches "color", "colour" |
| [abc] | Character class (a, b, or c) | [aeiou] matches vowels |
# Combining patterns
import re
# Match Australian phone numbers: 04XX-XXX-XXX
phone_pattern = r"04\d{2}-\d{3}-\d{3}"
text = "Call me at 0412-345-678 or 0498-765-432"
phones = re.findall(phone_pattern, text)
print(phones) # ['0412-345-678', '0498-765-432']
# Match email addresses
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
text = "Email [email protected] or [email protected]"
print(re.findall(email_pattern, text))
# ['[email protected]', '[email protected]']
Groups and Advanced Substitution
Capturing groups use parentheses to extract specific parts of a match. You can reference groups in substitutions using \1, \2, etc.
import re
# Capturing groups with ()
date_text = "Born on 15/03/2008"
match = re.search(r"(\d{2})/(\d{2})/(\d{4})", date_text)
if match:
day, month, year = match.groups()
print(f"Day: {day}, Month: {month}, Year: {year}")
# Day: 15, Month: 03, Year: 2008
# Named groups with (?P<name>...)
pattern = r"(?P<first>\w+)\s(?P<last>\w+)"
m = re.match(pattern, "Jane Smith")
print(m.group("first")) # Jane
print(m.group("last")) # Smith
# Substitution with groups - reformat dates
dates = "15/03/2008 and 22/07/2010"
reformatted = re.sub(r"(\d{2})/(\d{2})/(\d{4})", r"\3-\2-\1", dates)
print(reformatted) # 2008-03-15 and 2010-07-22
Key Vocabulary
Regular Expression
A pattern string used to match, search, and manipulate text based on rules and special characters.
Metacharacter
A character with special meaning in regex (e.g., ., *, +, ?, \d).
Capturing Group
A part of a regex enclosed in parentheses that extracts the matched text for later use.
Raw String
A string prefixed with r that treats backslashes as literal characters, essential for regex patterns.
Worked Examples
Validate an Australian postcode (4 digits)
import re
def is_valid_postcode(code):
"""Check if string is a valid 4-digit Australian postcode."""
pattern = r"^\d{4}$"
return bool(re.match(pattern, code))
print(is_valid_postcode("2000")) # True (Sydney)
print(is_valid_postcode("3000")) # True (Melbourne)
print(is_valid_postcode("123")) # False (too short)
print(is_valid_postcode("12345")) # False (too long)
print(is_valid_postcode("abcd")) # False (not digits)
^ and $ anchor the pattern to the start and end of the string, ensuring the entire string is exactly 4 digits.
Extract all hashtags from a social media post
import re
def extract_hashtags(text):
"""Find all #hashtags in text."""
return re.findall(r"#(\w+)", text)
post = "Loving #Python and #coding! #Year12 is challenging but fun"
tags = extract_hashtags(post)
print(tags) # ['Python', 'coding', 'Year12']
The parentheses around \w+ create a capturing group that returns just the tag name without the # symbol.
Censor profanity by replacing words with asterisks
import re
def censor_words(text, banned_words):
"""Replace banned words with asterisks."""
for word in banned_words:
pattern = re.compile(re.escape(word), re.IGNORECASE)
replacement = "*" * len(word)
text = pattern.sub(replacement, text)
return text
banned = ["spam", "scam"]
message = "This is SPAM and a Scam alert"
print(censor_words(message, banned))
# This is **** and a **** alert
re.IGNORECASE makes the match case-insensitive. re.escape() ensures special regex characters in the word are treated literally.
Knowledge Check
Select the correct answer for each question. Click "Check Answer" to see if you are right.
Question 1
What does \d+ match?
Question 2
What is the difference between re.search() and re.match()?
Question 3
What does re.findall(r"\w+", "Hello World") return?
Question 4
Why should you use raw strings (r"...") for regex patterns?
Question 5
What does re.sub(r"\s+", " ", text) do?
Key Concepts Summary
- ●Use re.search() to find the first match, re.findall() for all matches, and re.sub() for replacements.
- ●Common metacharacters: \d (digit), \w (word char), \s (whitespace), . (any char).
- ●Quantifiers + (one or more), * (zero or more), ? (optional) control repetition.
- ●Capturing groups with parentheses let you extract specific parts of a match.
- ●Always use raw strings (
r"...") for regex patterns to avoid backslash issues.