Regular expressions
A regular expression (regex) is a pattern that describes a set of strings. With the re module you can check whether text matches a pattern, find every match, or pull out the parts you care about. Regex is compact and powerful, and a little goes a long way.
Searching for a pattern
import re
text = "Order 4521 shipped on 15-09-2026"
m = re.search(r"\d+", text)
print(m.group())
print(m.start(), m.end())re.search finds the first match anywhere in the string and returns a match object, or None if nothing matches. Always write patterns as raw strings (r"...") so backslashes are passed through untouched.
The building blocks
| Pattern | Matches |
|---|---|
. | Any character except newline |
\d | A digit |
\w | A letter, digit or underscore |
\s | Whitespace |
[abc] | One of a, b or c |
[a-z] | One lowercase letter |
[^0-9] | Anything that is not a digit |
^ | Start of string |
$ | End of string |
a|b | a or b |
Quantifiers say how many times the thing before them may repeat:
| Quantifier | Meaning |
|---|---|
* | 0 or more |
+ | 1 or more |
? | 0 or 1 |
{3} | Exactly 3 |
{2,5} | 2 to 5 |
import re
print(re.search(r"^\d{4}$", "2026") is not None)
print(re.search(r"^\d{4}$", "20261") is not None)
print(re.search(r"colou?r", "color").group())Finding all matches
import re
text = "Call 98765 43210 or 91234 56789"
print(re.findall(r"\d{5} \d{5}", text))Groups
Parentheses capture parts of the match so you can pull them out separately.
import re
m = re.search(r"(\d{2})-(\d{2})-(\d{4})", "Due on 15-09-2026")
print(m.group(0))
print(m.group(1), m.group(2), m.group(3))
print(m.groups())Named groups make this readable:
import re
pattern = r"(?P<day>\d{2})-(?P<month>\d{2})-(?P<year>\d{4})"
m = re.search(pattern, "Due on 15-09-2026")
print(m.group("year"))
print(m.groupdict())Replacing
import re
print(re.sub(r"\s+", " ", "too many spaces"))
print(re.sub(r"(\w+)@(\w+)\.com", r"\1 at \2", "mail sara@indus.com now"))Splitting
import re
print(re.split(r"[,;]\s*", "a, b;c ,d"))Compiling a pattern
If you use a pattern many times, compile it once.
import re
email = re.compile(r"^[\w.+-]+@[\w-]+\.[\w.]+$")
for candidate in ["priya@example.com", "not an email", "a.b+c@dept.uni.in"]:
print(candidate, bool(email.match(candidate)))match checks only at the start of the string; search looks anywhere; fullmatch requires the whole string to match.
Flags
import re
print(re.findall(r"python", "Python is python", re.IGNORECASE))Greedy versus lazy
.* grabs as much as it can. Add ? to make it stop at the first opportunity.
import re
html = "<b>bold</b> and <i>italic</i>"
print(re.findall(r"<.*>", html))
print(re.findall(r"<.*?>", html))Practice
- Extract all hashtags from
"Learning #python and #ml this week #100DaysOfCode". - Validate Indian mobile numbers: ten digits starting with 6 to 9.
- Replace every date in
dd-mm-yyyyformat withyyyy-mm-ddusing groups.
