Home › Learn › Python › Strings in depth

Regular expressions

Lesson 29 of 40. Find and replace patterns in text with the re module.

A regular expression describes a pattern of characters. \d is a digit, \w a word character, + means one or more, * zero or more, \b a word boundary, [abc] any of those, and ^/$ the start and end. Write patterns as raw strings, r"\d+", so backslashes survive.

The re module does the work: re.findall(pattern, text) returns every match as a list, re.search finds the first match (or None), re.fullmatch checks the whole string, and re.sub(pattern, replacement, text) replaces. Pass flags=re.IGNORECASE to ignore case.

import re
print(re.findall(r"\d+", "3 cats, 12 dogs"))     # ['3', '12']
print(re.sub(r"\s+", " ", "too   many   spaces"))
print(bool(re.fullmatch(r"[a-z]+", "hello")))

Your task

Write find_numbers(text) returning every run of digits as an int, is_email_like(text) returning True when the whole string looks like something@something.something (letters, digits, dots, underscores, and hyphens on both sides of the @), and censor(text, word) replacing every whole-word occurrence of word, in any case, with ***.

Hint 1

[int(n) for n in re.findall(r"\d+", text)]

Hint 2

re.fullmatch(r"[\w.-]+@[\w-]+\.[\w.-]+", text) is not None; censor with re.sub(r"\b" + re.escape(word) + r"\b", "***", text, flags=re.IGNORECASE)

Show the solution
import re


def find_numbers(text):
    return [int(n) for n in re.findall(r"\d+", text)]


def is_email_like(text):
    return re.fullmatch(r"[\w.-]+@[\w-]+\.[\w.-]+", text) is not None


def censor(text, word):
    return re.sub(r"\b" + re.escape(word) + r"\b", "***", text, flags=re.IGNORECASE)

    Runs CPython compiled to WebAssembly in this tab (12 MB download the first time, then cached); nothing is sent anywhere.