Python Basics — Regular Expressions Intro

3 minute read

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 string
  • re.findall() returns all matches as a list
  • re.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 →

Updated: