Python Regular Expressions

In the last lesson, we learned about Python String Replacement. Now let’s find text by matching flexible patterns.

Let’s Talk About Patterns

We have a string. We want to find something in it. But not just a simple word. We want to find a pattern.

For example, we want to find all email addresses in a text. Or all phone numbers. Or all dates. Or all words that start with a capital letter.

We could write a loop and check character by character. But that would be a lot of work. And it would be messy.

That is what regular expressions are for.

A regular expression (often called regex) is a pattern that describes a set of strings. We use it to search, match, and replace text.

Think of it like a wildcard search, but much more powerful.

The re Module in Python

Python does not have regular expressions built into the language itself. Instead, it has a module called re. We import it and use its functions.

import re

Now we can use all the regex functions.

Our First Regex in Python

Let’s start simple. We want to find if a string contains the word “cat”.

import re
text = "I have a cat and a dog."
if re.search("cat", text):
print("Found cat!")

Output

Found cat!

re.search(pattern, string) scans the string and returns a match object if the pattern is found anywhere. If not found, it returns None.

So the if statement checks if a match was found.

Basic Regex Patterns in Python

The simplest pattern is just a literal string. Like “cat”. But regex becomes powerful when we use special characters.

Character Classes

  • \d matches any digit (0-9)
  • \w matches any word character (letters, digits, underscore)
  • \s matches any whitespace (space, tab, newline)
  • . matches any character except newline
text = "My number is 123."
match = re.search(r"\d+", text)
print(match.group())

Output

123

\d+ means one or more digits. The + is a quantifier.

Quantifiers in Python Regex

  • * zero or more
  • + one or more
  • ? zero or one
  • {n} exactly n times
  • {n,m} between n and m times
text = "aaa"
print(re.search(r"a{3}", text))

Output

<re.Match object; span=(0, 3), match='aaa'>

Anchors in Python Regex

  • ^ matches start of string
  • $ matches end of string
text = "Hello world"
print(re.search(r"^Hello", text))

Output

<re.Match object; span=(0, 5), match='Hello'>

Groups in Python Regex

We can group parts of a pattern with parentheses.

text = "My name is Alex"
match = re.search(r"My name is (\w+)", text)
print(match.group(1))

Output

Alex

The \w+ captures the name. group(1) gives the first captured group.

Common Functions in Python Regex

re.search()

Finds the first occurrence anywhere in the string.

re.search(r"cat", "I have a cat")

re.match()

Checks if the pattern matches at the beginning of the string.

re.match(r"cat", "cat is here") # matches
re.match(r"cat", "the cat") # no match

re.findall()

Returns a list of all non-overlapping matches.

text = "cats and dogs and cats"
print(re.findall(r"cat", text))

Output

['cat', 'cat']

re.sub()

Replaces all occurrences of the pattern with something else.

text = "Hello world"
print(re.sub(r"world", "Python", text))

Output

Hello Python

Python Regex: A Real-Life Example — Finding Email Addresses

Let’s find all email addresses in a block of text.

import re
text = """
Contact us at support@example.com or sales@example.org.
You can also reach me at alex.smith@company.co.uk.
"""
pattern = r"\b[\w.-]+@[\w.-]+\.\w+\b"
emails = re.findall(pattern, text)
print(emails)

Output

['support@example.com', 'sales@example.org', 'alex.smith@company.co.uk']

Let me explain the pattern.

  • \b word boundary
  • [\w.-]+ one or more word characters, dots, or hyphens
  • @ literal @
  • [\w.-]+ domain name
  • \. literal dot
  • \w+ top-level domain

This is a simplified pattern. Real email validation is more complex. But it works for many cases.

Another Example — Validating a Phone Number

import re
phone = "123-456-7890"
pattern = r"^\d{3}-\d{3}-\d{4}$"
if re.match(pattern, phone):
print("Valid phone number")
else:
print("Invalid phone number")

Output

Valid phone number

The pattern means: start, three digits, hyphen, three digits, hyphen, four digits, end.

Flags in Python Regex

We can modify how regex works with flags.

  • re.IGNORECASE or re.I — case-insensitive matching
  • re.MULTILINE or re.M — ^ and $ match at line breaks
  • re.DOTALL or re.S — . matches newline too
import re
text = "Hello World"
print(re.search(r"hello", text, re.IGNORECASE))

Output

<re.Match object; span=(0, 5), match='Hello'>

Raw Strings in Python Regex

When writing regex patterns, it is best to use raw strings. That is a string with an r before it.

pattern = r"\d+"

Without the r, we would have to escape backslashes. Like "\\d+". The raw string makes it cleaner.

When to Use Regex in Python

Regex is powerful. But it can also be hard to read. And it can be slow if used on very large texts.

Use regex when:

  • We need to find patterns, not just literal strings.
  • We need to validate input (emails, phone numbers, dates).
  • We need to extract parts of a string.

Do not use regex when:

  • A simple string method like in or find() will do.
  • The pattern is extremely complex. Sometimes writing a small parser is clearer.

A Word of Caution

Regex can become very complex very quickly. Let’s start simple. Test our patterns. Use online tools to help us debug. There are many regex testers available.

And remember: not all regex flavors are the same. Python’s re module has its own syntax. But it is close to standard regex.

Next, we will learn about Python Lists and store multiple values in one ordered collection.