A Regular Expression (Regex) is a powerful sequence of characters defining a search pattern. Python handles regular expressions via the built-in re module. Regex is vital for log processing, input validation, web scraping, search-and-replace pipelines, and data cleaning.
1. Regex Metacharacters & Character Sets Reference
Metacharacters are symbols with special meaning inside regular expression patterns.
A. Standard Metacharacters
| Symbol | Description | Example Pattern | Matches |
|---|---|---|---|
. |
Matches any single character except newline (unless re.DOTALL used). |
r"c.t" |
"cat", "cot", "c9t" |
^ |
Anchors match to the start of the string or line. | r"^Admin" |
"Admin User" (Starts with Admin) |
$ |
Anchors match to the end of the string or line. | r"end$" |
"The end" (Ends with end) |
* |
Matches 0 or more occurrences of preceding character/group. | r"go*l" |
"gl", "gol", "gool", "gooool" |
+ |
Matches 1 or more occurrences of preceding character/group. | r"go+l" |
"gol", "gool" (Not "gl") |
? |
Matches 0 or 1 occurrence (makes character optional or quantifier lazy). | r"colou?r" |
"color", "colour" |
{m,n} |
Matches between m and n occurrences. |
r"\d{2,4}" |
"12", "123", "1234" |
[] |
Matches any single character listed inside brackets. | r"[aeiou]" |
Any lowercase vowel |
| |
Alternation operator (OR condition). | r"cat|dog" |
"cat" or "dog" |
() |
Groups expressions together and captures matched sub-strings. | r"(\d{3})-(\d{4})" |
Captures area code and digits separately |
B. Special Character Sequences (Escaped Sequences)
| Sequence | Description | Equivalent Character Class |
|---|---|---|
\d |
Matches any Unicode decimal digit. | [0-9] |
\D |
Matches any non-digit character. | [^0-9] |
\w |
Matches word character (letters, numbers, underscore). | [a-zA-Z0-9_] |
\W |
Matches any non-word character. | [^a-zA-Z0-9_] |
\s |
Matches whitespace character (space, tab, newline, return). | [ \t\n\r\f\v] |
\S |
Matches any non-whitespace character. | [^ \t\n\r\f\v] |
\b |
Word boundary anchor (position between \w and \W). |
N/A |
2. Core `re` Module API Functions
3. Advanced Regex Concepts: Groups, Flags, and Lookarounds
A. Grouping & Named Captures
Parentheses () capture matched sub-expressions into numbered groups (1, 2, 3...). Python also supports named groups using syntax (?P<name>pattern).
B. Regex Compilation Flags
re.IGNORECASE/re.I: Case-insensitive matching.re.MULTILINE/re.M: Makes^and$match start/end of each line in multi-line strings.re.DOTALL/re.S: Makes dot.match newline characters\nas well.re.VERBOSE/re.X: Allows whitespaces and inline comments inside regex pattern for readability.
C. Lookahead and Lookbehind Assertions (Lookarounds)
Lookarounds match a pattern based on what precedes or follows it without including that text in the captured match result.
| Type | Syntax | Description | Example Pattern & Result |
|---|---|---|---|
| Positive Lookahead | (?=pattern) |
Asserts that following text matches pattern. | r"\d+(?=\s*USD)" on "100 USD" ➔ Matches "100" |
| Negative Lookahead | (?!pattern) |
Asserts that following text does NOT match pattern. | r"\d+(?!\s*USD)" on "100 EUR" ➔ Matches "100" |
| Positive Lookbehind | (?<=pattern) |
Asserts that preceding text matches pattern. | r"(?<=\$)\d+" on "$250" ➔ Matches "250" |
| Negative Lookbehind | (?<!pattern) |
Asserts that preceding text does NOT match pattern. | r"(?<!VIP-)\w+" on "User1" ➔ Matches "User1" |
🏋️ Try It Yourself: Practice Challenges
Write a script using re.findall() and named groups that extracts all valid email addresses from an unformatted block of text, separating username and domain components.
Using re.sub() combined with lookbehind assertions ((?<=...)), automatically mask all credit card numbers and phone numbers in a server log string while leaving preceding transaction IDs untouched.
Design a function using lookaheads ((?=.*[A-Z]), (?=.*\d), (?=.*[@$!%*?&])) that tests whether a candidate password string contains at least 8 characters, one uppercase letter, one digit, and one special character.
Construct a regex replacement pipeline using re.sub() that converts CamelCase identifiers (e.g., "CalculateTotalUserScore") into lowercase snake_case (e.g., "calculate_total_user_score").
Write a non-greedy regex search pattern using lazy quantifiers (.*?) that strips out all HTML tags from an HTML snippet while preserving text content between tags.