Regular Expressions — the re Module
Advancedsearch finds, findall collects, sub replaces, groups extract — with raw strings, character classes and quantifiers making Python a text-processing power tool.
Overview
Regex is a mini-language for describing text patterns — validation (emails, phone numbers), extraction (IDs from logs), and transformation (sub with backreferences). The re module API is small: search (first match anywhere), match (only at the start), findall (all matches), sub (replace), finditer (lazy match objects). Two habits prevent most regex pain: always write patterns as raw strings r"...", and reach for groups (...) to pull out the parts you actually want.
The Five Functions
Match objects hold .group() / .groups() / .start(). findall returns strings (or tuples if groups). Compile once when reusing a pattern in a loop.
import re
log = "2026-07-10 ERROR user=asha code=500; 2026-07-10 INFO user=ravi code=200"
# search — first occurrence anywhere
m = re.search(r"code=(\d+)", log)
print(m.group(0), m.group(1)) # code=500 500
# findall — everything, capture groups only
print(re.findall(r"user=(\w+)", log)) # ['asha', 'ravi']
# sub — replace (mask phone numbers)
txt = "call 9876543210 or 9123456789"
print(re.sub(r"\d{10}", "XXXXXXXXXX", txt))
# Named groups — self-documenting extraction
pat = re.compile(r"(?P<date>\d{4}-\d{2}-\d{2}) (?P<level>\w+)")
for m in pat.finditer(log):
print(m["date"], m["level"]) # 2026-07-10 ERROR / INFO
# match vs search: match anchors at position 0
print(re.match(r"\d+", "abc123")) # None
print(re.search(r"\d+", "abc123")) # <re.Match ... '123'>Pattern Vocabulary You Must Know
Classes (\d \w \s), quantifiers (* + ? {m,n}), anchors (^ $ \b), alternation (|), and the greedy-vs-lazy distinction (.* vs .*?) — enough for 90% of real patterns.
import re
# Indian mobile: optional +91, then 10 digits starting 6-9
mobile = re.compile(r"^(?:\+91[- ]?)?[6-9]\d{9}$")
print(bool(mobile.match("+91 98765 43210".replace(" ", "")))) # True
print(bool(mobile.match("1234567890"))) # False
# Simple email shape (real validation is looser — send a link!)
email = re.compile(r"^[\w.+-]+@[\w-]+\.[\w.]+$")
print(bool(email.match("asha.k+test@aicancode.org"))) # True
# Greedy vs lazy — the classic trap
html = "<b>bold</b> and <i>italic</i>"
print(re.findall(r"<(.*)>", html)) # ['b>bold</b> and <i>italic</i'] !!
print(re.findall(r"<(.*?)>", html)) # ['b', '/b', 'i', '/i'] — lazy
# Word boundaries — whole words only
print(re.sub(r"\bjava\b", "python", "java javascript java"))
# python javascript python (javascript untouched)
# Split on multiple delimiters
print(re.split(r"[,;|]\s*", "a, b; c| d")) # ['a','b','c','d']Key Points to Remember
- 1Always raw strings: r"\d+" — otherwise Python eats your backslashes
- 2search anywhere vs match at start; findall returns group contents
- 3.* is greedy (longest), .*? is lazy (shortest) — the #1 regex bug
- 4Groups (...) extract; named groups (?P<name>...) document; \b bounds whole words
Interview Questions
Sign in to ask AriaDifference between re.match and re.search?
Write a regex for Indian mobile numbers with optional +91 prefix.
Explain greedy vs lazy quantifiers with the HTML-tag example.
Ask Aria about Regular Expressions — the re Module
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.