indusai.co

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

python
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

PatternMatches
.Any character except newline
\dA digit
\wA letter, digit or underscore
\sWhitespace
[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|ba or b

Quantifiers say how many times the thing before them may repeat:

QuantifierMeaning
*0 or more
+1 or more
?0 or 1
{3}Exactly 3
{2,5}2 to 5
python
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

python
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.

python
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:

python
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

python
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

python
import re
print(re.split(r"[,;]\s*", "a, b;c ,d"))

Compiling a pattern

If you use a pattern many times, compile it once.

python
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

python
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.

python
import re
html = "<b>bold</b> and <i>italic</i>"
print(re.findall(r"<.*>", html))
print(re.findall(r"<.*?>", html))

Practice

  1. Extract all hashtags from "Learning #python and #ml this week #100DaysOfCode".
  2. Validate Indian mobile numbers: ten digits starting with 6 to 9.
  3. Replace every date in dd-mm-yyyy format with yyyy-mm-dd using groups.