AI Skill Report Card

Using Python Regex

A-85·Aug 14, 2026·Source: Web

Using Python Regex (re module)

14 / 15
Python
import re # Compile once, reuse often pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b') text = "Contact: alice@example.com or bob@test.org" matches = pattern.findall(text) # ['alice@example.com', 'bob@test.org'] # Single search m = re.search(r'\d+', "Order #4521") if m: print(m.group()) # '4521'
Recommendation
Add an example showing a bad/incorrect regex outcome (e.g., greedy match failure) alongside the fix for contrast
13 / 15

Progress:

  • Step 1: Define the exact string shape you need to match (be explicit about anchors, boundaries, optional parts)
  • Step 2: Choose the right function (match, search, findall, finditer, sub, split)
  • Step 3: Write the pattern using raw strings (r"...") to avoid escape confusion
  • Step 4: Use named groups (?P<name>...) for clarity when extracting multiple fields
  • Step 5: Compile the pattern with re.compile() if reused in a loop or called repeatedly
  • Step 6: Test against edge cases (empty string, multiline, unicode, overlapping matches)
  • Step 7: Apply flags (re.IGNORECASE, re.MULTILINE, re.DOTALL, re.VERBOSE) as needed
  • Step 8: Verify no catastrophic backtracking on large/adversarial inputs
Recommendation
Include a brief section on performance considerations for very large inputs beyond backtracking
FunctionPurposeReturns
re.match(p, s)Match at start of string onlyMatch object or None
re.fullmatch(p, s)Entire string must matchMatch object or None
re.search(p, s)Find first match anywhereMatch object or None
re.findall(p, s)Find all non-overlapping matchesList of strings/tuples
re.finditer(p, s)Find all matches, lazilyIterator of Match objects
re.sub(p, repl, s)Replace matchesNew string
re.subn(p, repl, s)Replace + countTuple (string, count)
re.split(p, s)Split string by patternList of strings
18 / 20

Example 1: Extracting structured data with named groups Input:

Python
log = "2024-01-15 ERROR: Connection failed" pattern = re.compile(r'(?P<date>\d{4}-\d{2}-\d{2})\s+(?P<level>\w+):\s+(?P<msg>.+)') m = pattern.match(log)

Output:

Python
m.group('date') # '2024-01-15' m.group('level') # 'ERROR' m.group('msg') # 'Connection failed' m.groupdict() # {'date': '2024-01-15', 'level': 'ERROR', 'msg': 'Connection failed'}

Example 2: Substitution with a function Input:

Python
text = "price: 100, discount: 20" result = re.sub(r'\d+', lambda m: str(int(m.group()) * 2), text)

Output:

Python
"price: 200, discount: 40"

Example 3: Splitting on multiple delimiters Input:

Python
re.split(r'[,;]\s*', "apple, banana;cherry, date")

Output:

Python
['apple', 'banana', 'cherry', 'date']

Example 4: Verbose mode for readable complex patterns Input:

Python
pattern = re.compile(r""" (?P<area>\d{3}) # area code - (?P<num>\d{4}) # number """, re.VERBOSE) pattern.match("555-1234").groupdict()

Output:

Python
{'area': '555', 'num': '1234'}
Recommendation
Consider trimming the Best Practices and Pitfalls lists slightly to tighten overall length, as some points overlap
  • Always use raw strings (r"...") for patterns to avoid double-escaping backslashes.
  • Use re.compile() when the same pattern runs many times (loops, per-request validation).
  • Prefer non-capturing groups (?:...) when you don't need to extract that group, for performance and clarity.
  • Use \b word boundaries to avoid partial-word matches (e.g., matching "cat" inside "category").
  • Use re.VERBOSE with inline comments for patterns longer than ~40 characters.
  • Anchor patterns (^, $, \A, \Z) when the entire string must conform to a format — use fullmatch() instead of match() when validating full strings.
  • For known-safe literal text, use re.escape() before inserting user input into a pattern.
  • Use finditer() instead of findall() when you need match positions (.start(), .end()) or when working with large text (lazy iteration).
  • Greedy quantifiers by default.* grabs as much as possible; use .*? for lazy/minimal matching when needed.
  • Forgetting re.DOTALL. does not match newlines by default; multiline text needs re.DOTALL if you want . to span lines.
  • Confusing match() vs search()match() only anchors at the start of the string, not the whole string; unexpected None results often come from this.
  • Unescaped special characters — literal ., *, +, (, ), [, ], {, }, |, ^, $, \ must be escaped or passed through re.escape().
  • Catastrophic backtracking — nested quantifiers like (a+)+ on adversarial input can hang; prefer possessive-like restructuring or bound repetition counts.
  • Ignoring compiled flags scope — flags set inside (?i) apply differently across Python versions/positions; prefer passing flags explicitly to re.compile().
  • Using regex for deeply nested/structured data — HTML, JSON, or nested parentheses are not reliably parseable with regex; use a proper parser instead.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
13/15
Examples
18/20
Completeness
18/20
Format
14/15
Conciseness
14/15