Key Takeaways: Regular Expressions

One-Sentence Summary

Regular expressions are a concise pattern-matching language that lets you find, extract, validate, and transform text in ways that plain string methods cannot — but knowing when not to use regex is just as important as knowing how.

The re Module at a Glance

Function What It Does Returns
re.search(pat, s) Find first match anywhere Match object or None
re.match(pat, s) Match at start only Match object or None
re.fullmatch(pat, s) Match entire string Match object or None
re.findall(pat, s) Find all matches List of strings/tuples
re.finditer(pat, s) Loop over all matches Iterator of match objects
re.sub(pat, repl, s) Replace all matches New string
re.split(pat, s) Split on pattern List of strings
re.compile(pat) Precompile for reuse Pattern object

Building Blocks

Concept Syntax Example Matches
Character class [abc], \d, \w, \s \d{3} Three digits
Quantifier +, *, ?, {n,m} \w+ One or more word chars
Anchor ^, $, \b ^ERROR "ERROR" at start of line
Group (pattern) (\d{4})-(\d{2}) Year and month captured
Named group (?P<name>pat) (?P<year>\d{4}) Access via group("year")
Alternation a\|b gr(?:a\|e)y "gray" or "grey"
Escaped metacharacter \., \$`, `\(` | `\$\d+\.\d{2} A price like "$4.99"
Lazy quantifier *?, +? <.*?> Shortest match between <>

Critical Distinctions

Greedy (*, +) Lazy (*?, +?)
Matches as much as possible Matches as little as possible
Default behavior Add ? after quantifier
Use for: unbounded patterns (\d+) Use for: content between delimiters (<.*?>)

When to Use Regex vs. String Methods

Use String Methods Use Regex
Finding/replacing an exact substring Matching variable formats
Splitting on a single delimiter Extracting multiple fields
Checking startswith()/endswith() Validating complex patterns
Stripping whitespace Splitting on multiple delimiters
Simple, fixed-format tasks Anything involving character classes or groups

Common Pitfalls

  1. Forgetting r prefix — "\b" is a backspace; r"\b" is a word boundary (and "\d" triggers a SyntaxWarning)
  2. Using re.match() when you mean re.search() — match() only checks the start; use fullmatch() to validate a whole string
  3. Forgetting to escape metacharacters — . matches any character; write \. for a real period
  4. Greedy matching between delimiters — "<.*>" matches too much; use "<.*?>" or "<[^>]*>"
  5. Surprise groups in findall() — adding parentheses changes what findall() returns; use (?:...) if you only need grouping
  6. Passing flags positionally to re.sub() or re.split() — the fourth argument is count/maxsplit; write flags=re.IGNORECASE
  7. Overly complex regex — if a colleague can't read it in 30 seconds, simplify or use string methods; for CSV, JSON, or HTML, use a real parser

TaskFlow v2.1 Additions

  • Regex-powered search: users can filter tasks with patterns like "^Buy" or "meeting|call"; an uncompilable pattern (re.error) falls back to plain substring search
  • Natural language date parsing: "next Tuesday", "tomorrow", "in 3 days" are interpreted as real dates using re.fullmatch() with capture groups

What's Next

Chapter 23: Virtual environments, pip, requirements.txt, and the ecosystem of third-party libraries.