Python Basics — Regular Expressions Intro
Regular Expressions Intro
Regular expressions (regex) are patterns for matching text. They’re a powerful tool for searching, validating, and extracting data from strings.
The re Module
import re
Python’s re module provides all regex functionality.
re.search() — Find First Match
import re
text = "My phone is 123-456-7890"
match = re.search(r"\d{3}-\d{3}-\d{4}", text)
if match:
print(f"Found: {match.group()}") # Found: 123-456-7890
re.search() scans the entire string and returns the first match (or None).
re.match() — Match at Start
import re
# match() only checks the beginning of the string
result = re.match(r"\d+", "123abc")
print(result.group()) # 123
result = re.match(r"\d+", "abc123")
print(result) # None (doesn't start with digits)
re.findall() — Find All Matches
import re
text = "Prices: $10, $25, $3, and $150"
prices = re.findall(r"\$\d+", text)
print(prices) # ['$10', '$25', '$3', '$150']
# Extract just the numbers
numbers = re.findall(r"\d+", "abc 123 def 456 ghi 789")
print(numbers) # ['123', '456', '789']
re.sub() — Search and Replace
import re
text = "Call 123-456-7890 or 098-765-4321"
redacted = re.sub(r"\d{3}-\d{3}-\d{4}", "XXX-XXX-XXXX", text)
print(redacted) # Call XXX-XXX-XXXX or XXX-XXX-XXXX
# Remove extra whitespace
messy = "too many spaces here"
clean = re.sub(r"\s+", " ", messy)
print(clean) # too many spaces here
Common Patterns
Character Classes
| Pattern | Matches | Example |
|---|---|---|
\d |
Any digit (0-9) | re.findall(r"\d+", "age 25") → ['25'] |
\D |
Any non-digit | re.findall(r"\D+", "age 25") → ['age '] |
\w |
Word char (a-z, A-Z, 0-9, _) | re.findall(r"\w+", "hi there") → ['hi', 'there'] |
\W |
Non-word char | re.findall(r"\W+", "hi there!") → [' ', '!'] |
\s |
Whitespace | re.findall(r"\s+", "a b c") → [' ', ' '] |
. |
Any char (except newline) | re.findall(r"h.t", "hat hit hot") → ['hat', 'hit', 'hot'] |
Quantifiers
| Pattern | Meaning | Example |
|---|---|---|
* |
0 or more | r"ab*c" matches ac, abc, abbc |
+ |
1 or more | r"ab+c" matches abc, abbc but not ac |
? |
0 or 1 | r"colou?r" matches color and colour |
{n} |
Exactly n | r"\d{3}" matches 123 |
{n,m} |
Between n and m | r"\d{2,4}" matches 12, 123, 1234 |
Anchors
| Pattern | Meaning |
|---|---|
^ |
Start of string |
$ |
End of string |
\b |
Word boundary |
import re
# Start and end anchors
print(re.match(r"^\d{5}$", "12345")) # Match (exactly 5 digits)
print(re.match(r"^\d{5}$", "1234")) # None (only 4 digits)
print(re.match(r"^\d{5}$", "123456")) # None (6 digits)
Practical Examples
Email Validation (Simple)
import re
def is_valid_email(email):
pattern = r"^[\w.+-]+@[\w-]+\.[\w.]+$"
return bool(re.match(pattern, email))
print(is_valid_email("user@example.com")) # True
print(is_valid_email("user.name@mail.co.uk")) # True
print(is_valid_email("invalid@")) # False
print(is_valid_email("@example.com")) # False
Phone Number Extraction
import re
text = """
Contact us at:
(555) 123-4567
555-123-4567
555.123.4567
5551234567
"""
pattern = r"\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}"
phones = re.findall(pattern, text)
print(phones)
# ['(555) 123-4567', '555-123-4567', '555.123.4567', '5551234567']
URL Extraction
import re
text = "Visit https://example.com or http://test.org/page for more."
urls = re.findall(r"https?://[\w./%-]+", text)
print(urls) # ['https://example.com', 'http://test.org/page']
Groups — Capturing Parts of a Match
import re
text = "Date: 2025-03-15"
match = re.search(r"(\d{4})-(\d{2})-(\d{2})", text)
if match:
print(f"Full: {match.group()}") # 2025-03-15
print(f"Year: {match.group(1)}") # 2025
print(f"Month: {match.group(2)}") # 03
print(f"Day: {match.group(3)}") # 15
Named Groups
import re
pattern = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
match = re.search(pattern, "Date: 2025-03-15")
if match:
print(match.group("year")) # 2025
print(match.group("month")) # 03
print(match.group("day")) # 15
When to Use Regex vs String Methods
| Task | String Method | Regex |
|---|---|---|
| Simple contains check | "x" in text |
Overkill |
| Exact replacement | text.replace("a", "b") |
Overkill |
| Split on one delimiter | text.split(",") |
Overkill |
| Pattern matching | Not possible | re.search(pattern, text) |
| Multiple delimiters | Complex | re.split(r"[,;\s]+", text) |
| Validation | Tedious | re.match(pattern, text) |
Rule of thumb: Start with string methods. Use regex when the pattern is too complex or variable for string methods.
Summary
re.search()finds the first match anywhere in the stringre.findall()returns all matches as a listre.sub()replaces matches with a new string\d= digits,\w= word chars,\s= whitespace,.= any char- Quantifiers:
*(0+),+(1+),?(0 or 1),{n}(exactly n) - Use raw strings (
r"...") for regex patterns to avoid escape issues - Groups
()capture parts of a match for extraction - Prefer string methods for simple operations; use regex for complex patterns
Next up: Practice Exercises →