
Python Regex Cheatsheet: Practical Patterns for Everyday Text
Regular expressions are easiest to learn when you connect each pattern to a real task. In Python, the re module gives you the basic tools: find, validate, capture, split, and replace.
Start with this mental model: a regex does not describe what a string “means”. It describes the shape of text you want to match.
1. Import re and use raw strings
Always write regex patterns as raw strings with r"...". It keeps backslashes readable and avoids accidental Python string escapes.
import re
text = "Order #A-1042 ships on 2026-08-19"
match = re.search(r"#([A-Z]-\d+)", text)
if match:
print(match.group(1)) # A-1042
2. Common building blocks
Here are the pieces you will reuse constantly:
| Pattern | Meaning | Example match |
|---|---|---|
\d |
digit | 7 |
\w |
word character | a, Z, _, 3 |
\s |
whitespace | space, tab, newline |
. |
any character except newline | x |
+ |
one or more | aaa |
* |
zero or more | empty or aaa |
? |
optional | empty or one |
{2,4} |
between 2 and 4 times | 12, 1234 |
^ |
start of string | start only |
$ |
end of string | end only |
3. Validate a simple email shape
Email validation can get extremely complicated. For product forms, you usually want a practical first-pass check, not the entire email RFC.
import re
pattern = r"^[\w.+-]+@[\w-]+(?:\.[\w-]+)+$"
emails = [
"ada@example.com",
"first.last+tag@sub.example.co",
"not-an-email",
]
for email in emails:
print(email, bool(re.fullmatch(pattern, email)))
Use fullmatch() when the whole string must match. Use search() when the pattern may appear anywhere inside a larger string.
4. Capture dates
Parentheses create capture groups. They let you extract the parts you care about.
import re
text = "Published: 2026-08-19"
match = re.search(r"(\d{4})-(\d{2})-(\d{2})", text)
if match:
year, month, day = match.groups()
print(year, month, day)
Named groups are clearer when a pattern grows:
import re
pattern = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
match = re.search(pattern, "Published: 2026-08-19")
if match:
print(match.groupdict())
5. Extract all matching values
Use findall() for simple extraction and finditer() when you also need positions or named groups.
import re
text = "Errors: E100, E203, E404"
print(re.findall(r"E\d{3}", text))
for match in re.finditer(r"E\d{3}", text):
print(match.group(), match.start(), match.end())
6. Replace messy whitespace
re.sub() is perfect for cleanup tasks.
import re
raw = "Python regex\ncan\tclean text"
clean = re.sub(r"\s+", " ", raw).strip()
print(clean) # Python regex can clean text
You can also use capture groups inside replacements:
import re
text = "2026/08/19"
iso = re.sub(r"(\d{4})/(\d{2})/(\d{2})", r"\1-\2-\3", text)
print(iso) # 2026-08-19
7. Split on flexible separators
When data comes from humans, separators are rarely consistent.
import re
text = "python, regex; parsing | cleanup"
parts = re.split(r"\s*[,;|]\s*", text)
print(parts) # ['python', 'regex', 'parsing', 'cleanup']
8. Use non-capturing groups for structure
If you need grouping but do not need to extract that group, use (?:...).
import re
pattern = r"https?://(?:www\.)?example\.com/\w+"
print(bool(re.search(pattern, "Visit https://www.example.com/docs")))
That keeps match.groups() focused on values you actually want.
9. Make patterns readable with re.VERBOSE
Long regexes become much easier to maintain when you spread them over multiple lines and add comments.
import re
phone_pattern = re.compile(r"""
^
\+? # optional country prefix
\d{1,3}? # country code
[\s.-]?
\(?\d{2,4}\)? # area code
[\s.-]?
\d{3,4}
[\s.-]?
\d{4}
$
""", re.VERBOSE)
print(bool(phone_pattern.fullmatch("+1 415 555 0133")))
10. Compile patterns you reuse
For one-off checks, calling re.search() directly is fine. For repeated matching, compile the pattern once.
import re
slug_re = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
for slug in ["python-regex", "Bad Slug", "notes-2026"]:
print(slug, bool(slug_re.fullmatch(slug)))
A small checklist
- Use raw strings:
r"\d+" - Prefer
fullmatch()for validation - Prefer named groups for important captures
- Use
finditer()when you need match positions - Use
re.VERBOSEfor patterns that future-you must read - Keep validation regexes practical unless you truly need a full specification
Regex becomes less mysterious once you stop trying to memorize everything. Learn the small pieces, combine them carefully, and test each pattern against real examples.