Python Regular Expressions

In the last lesson you learned String Replacement. There you swapped one piece of text for another. That works great when you know the exact text you are looking for. But what about when you don’t? Say you want to find every phone number in a message. Or you want to check if some text looks like an email. You don’t know the exact characters. You only know the shape. That is what regular expressions are for.

🤔 Why Regular Expressions?

Imagine Riya is building a sign-up form. She wants to check that the email someone typed actually looks like an email. With plain string methods, this gets messy fast.

Here is the kind of thing she ends up writing without regex. It checks a few conditions by hand and still misses cases.

email = "riya@example.com"
# ❌ Avoid: checking the "shape" of text by hand
looks_ok = "@" in email and "." in email and " " not in email
print(looks_ok)

Output

True

See the problem? That same check also passes for text that is clearly not an email, as long as it has an at sign and a dot. To really describe the shape of valid text by hand, you would need pages of if statements.

A regular expression lets you describe that shape in one short pattern. Then Python checks the text against it for you. So the messy pile of if checks becomes one clean line.

🧩 What Is a Regular Expression?

A regular expression (we usually say regex for short) is a small pattern that describes what text should look like. Think of it like a search that understands shapes, not just exact words.

Here is a everyday way to picture it. A normal search is like asking “find the word cat”. A regex is like asking “find any three letters where the middle one is a vowel”. You are describing a pattern, not one fixed word.

Python has this built in. You bring it in with one line.

import re

That re stands for “regular expressions”. Every function we use below lives inside it.

🔤 A Few Basic Pattern Pieces

Before we match anything, you need a handful of building blocks. These are special characters that mean “a kind of character” instead of that exact character.

Here are the few we will use, kept simple.

Piece What it means Example match
\d Any single digit, 0 to 9 the 7 in "box7"
+ One or more of the thing before it \d+ matches "42"
. Almost any single character matches a, 7, or ?

So \d is one digit. Put + after it and \d+ means a whole run of digits, like a full number. That + is the part that makes regex feel powerful, so keep it in mind.

Tip

Always write your patterns as a raw string with an r in front, like r"\d+". Without the r, Python may treat the backslash as something else. The r tells Python to leave the backslash alone and hand it straight to the regex.

🔎 re.search: Is the Pattern in There?

The first job is simple. You have some text. You want to know if a pattern shows up anywhere in it. That is re.search.

Here we check whether a sentence contains any digit at all.

import re
text = "Order 42 is ready"
result = re.search(r"\d+", text)
if result:
print("Found a number:", result.group())
else:
print("No number here")

Output

Found a number: 42

Let’s walk through it line by line.

  • re.search(r"\d+", text) looks through text for the first run of digits.
  • If it finds something, it hands back a match object. If it finds nothing, it hands back None.
  • if result: is True when a match was found. A real match object counts as true and None counts as false.
  • result.group() gives you the actual text that matched, here the string "42".

So here is the why. re.search answers the yes-or-no question “does this pattern appear?” And when it does, it also hands you the matching piece.

📋 re.findall: Give Me Every Match

re.search stops at the first match. But often you want all of them. Say a message has several numbers and you want every one. That is re.findall.

Here we pull every run of digits out of a sentence.

import re
text = "Riya scored 88, Alex scored 92, Arjun scored 75"
numbers = re.findall(r"\d+", text)
print(numbers)

Output

['88', '92', '75']

A few things to notice here.

  • re.findall returns a plain list of strings, one for each match it found.
  • Each item is text, not a number yet. '88' is a string, so you would convert it with int() if you wanted to add them up.
  • If nothing matches, you get back an empty list, not an error.

That is the everyday use of regex. You scan a block of text and collect every piece that fits the shape.

🔁 re.sub: Find and Replace by Pattern

Remember string replacement from the last lesson? re.sub is the same idea, but it replaces by pattern instead of by exact text. So you can replace every number, every space, anything that matches a shape.

Here we hide every number in a message by swapping it for #.

import re
text = "Call me at 555 1234 today"
clean = re.sub(r"\d+", "#", text)
print(clean)

Output

Call me at # # today

Reading it across.

  • The first part, r"\d+", is the pattern to find: any run of digits.
  • The second part, "#", is what to put in its place.
  • The third part, text, is the text to work on.

So every group of digits became a single #. The 555 and the 1234 each turned into one #. This is handy for hiding private details like phone numbers before you show text to someone.

🛠️ One Small Real Example

Let’s tie it together. Say Alex gets a messy line of text. He just wants the numbers out of it, as real numbers he can add up.

This finds every number in the line, turns each one into an int, and sums them.

import re
line = "apples 12, oranges 7, pears 21"
found = re.findall(r"\d+", line)
totals = [int(n) for n in found]
print("Numbers found:", totals)
print("Total fruit:", sum(totals))

Output

Numbers found: [12, 7, 21]
Total fruit: 40

Walking through it.

  • re.findall(r"\d+", line) grabs ['12', '7', '21'], every run of digits as text.
  • [int(n) for n in found] walks that list and turns each string into a real number.
  • sum(totals) adds them up to 40.

In a few lines you went from a messy sentence to clean numbers you can do math with. Doing that by hand with string slicing would be a real headache.

⚠️ Common Mistakes

A few things trip people up early with regex.

  • Forgetting the r in front of the pattern. Always write r"\d+", not "\d+", so the backslash reaches the regex safely.
  • Forgetting to import re at the top. Without it, every re.search line raises a NameError.
  • Thinking re.findall gives you numbers. It gives you strings. Convert with int() before doing math.
import re
found = re.findall(r"\d+", "score 88")
# ❌ Avoid: trying to add a string and a number
# print(found[0] + 2) # this would crash
# ✅ Good: convert to int first
print(int(found[0]) + 2)

Output

90

Caution

Regex can get complicated quickly once you start matching real things like full emails. That is fine. This lesson is just your first look. Start with \d, +, and ., get comfortable, and add more pieces later.

✅ Best Practices

A few habits that keep regex friendly.

  • Always use raw strings for patterns: r"...". Make it a reflex.
  • Start with the simplest pattern that works. You can always make it stricter later.
  • When you only need a yes-or-no answer, use re.search. When you need every match, use re.findall.
  • Test your pattern on a small piece of text first, then use it on the real data.

🧩 What You’ve Learned

You took your first look at regular expressions in Python. Here is the quick recap.

  • ✅ Regex lets you describe the shape of text instead of an exact word.
  • ✅ You bring the tools in with import re.
  • \d means one digit, + means one or more, and . means almost any character.
  • re.search tells you if a pattern appears and hands back the first match.
  • re.findall returns a list of every match.
  • re.sub replaces every match with text you choose.
  • ✅ Matches come back as strings, so convert with int() when you need numbers.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does the pattern \d+ match?

    Why: \d means a single digit and + means one or more, so \d+ matches a run of one or more digits.

  2. 2

    Which function returns a list of every match in the text?

    Why: re.findall scans the whole text and returns a list with every piece that matches the pattern.

  3. 3

    Why should you write patterns as raw strings like r"\d+"?

    Why: The r prefix keeps Python from treating the backslash specially, so the regex receives the pattern exactly as written.

  4. 4

    What does re.findall(r"\d+", "a1 b22") return?

    Why: re.findall returns a list of strings, so each matched run of digits comes back as text, not as a number.

🚀 What’s Next?

You have been working with single pieces of text so far. Next you will learn how to hold many values together in one place. That is where a lot of real Python begins.

Introduction to Lists

Share & Connect