hayaliv / Hi! Python / Level 1
Regular expressions, the basics
Find, extract and replace text patterns with re.search, re.findall and re.sub.
Think of it like this
A regular expression is like a stencil you lay over a page. Only the words that fit the holes show through.
Where the analogy stops being true. A stencil has a fixed shape, while a regex is written by you and can fit more or less than you meant.
What to know
re.search(pattern, text)returns the first match, orNonewhen nothing matches.re.findallreturns all non-overlapping matches as a list.re.sub(pattern, repl, text)returns a new string with each match replaced.- The docs highly recommend raw strings,
r"...", for patterns. Python then leaves the backslashes alone forreto read. - Brackets
( )make groups.Match.group(1)returns the text of the first group, andfindallreturns tuples when there are several groups. - The email pattern in the example is a rough guess, not a full email checker. The last predict item shows it can miss an address.
- A regex can match less or more than you meant, so check the output by eye.
Example
import re
EMAIL = r"[\w.]+@[\w.]+\.\w+"
reply = "Thanks! Reach me at jane.doe@example.com or sam@corp.io, call 5pm."
m = re.search(EMAIL, reply)
print(m.group())
print(re.findall(EMAIL, reply))
print(re.sub(EMAIL, "<EMAIL>", reply))
m2 = re.search(r"([\w.]+)@([\w.]+\.\w+)", reply)
print(m2.group(1), "|", m2.group(2))
print(re.findall(r"([\w.]+)@([\w.]+\.\w+)", reply))
It prints:
jane.doe@example.com
['jane.doe@example.com', 'sam@corp.io']
Thanks! Reach me at <EMAIL> or <EMAIL>, call 5pm.
jane.doe | example.com
[('jane.doe', 'example.com'), ('sam', 'corp.io')]
Predict, then check
1. What does this print?
import re
print(re.search(r"\d+", "no digits here"))Show the answer
NoneThere is no digit anywhere, so search returns None.
2. What does this print?
import re
print(re.sub(r"\d", "#", "call 555-1234"))Show the answer
call ###-####Every single digit is replaced by #, and the dash is left alone.
3. What does this print?
import re
print(re.findall(r"[\w.]+@[\w.]+\.\w+", "ping a@b or c@d.org"))Show the answer
['c@d.org']The pattern needs a dot after the @ part, so a@b is missed. This shows a simple regex can miss things.
4. What does this print?
import re
try:
re.search(r"\d", "abc").group()
except AttributeError:
print("no match")Show the answer
no matchsearch returned None, and None has no group method, so AttributeError is raised.
Try it
Write mask_emails(text). Replace every email-like piece (use the pattern r"[\w.]+@[\w.]+\.\w+") with <EMAIL> and return the new text.
def mask_emails(text):
return text
Show a solution
import re
def mask_emails(text):
return re.sub(r"[\w.]+@[\w.]+\.\w+", "<EMAIL>", text)Common mistake
re.search returns None when nothing matches, so calling .group() on the result can fail. Test the result first with if m:, because a match object is always true.
In a small-language-model project
Before putting real cold-email replies into a training file, you may want to mask email addresses with re.sub. A regex may catch only some personal data, so treat it as a first pass and still look at samples.
Sources
Each quote below appears word for word on the cited page of the official Python documentation (version 3.12).
Scan through string looking for the first location where the regular expression pattern produces a match, and return a corresponding Match . Return None if no position in the string matches the pattern
docs.python.org/3.12/library/re.html — search finds the first match or returns None.Return all non-overlapping matches of pattern in string , as a list of strings or tuples.
docs.python.org/3.12/library/re.html — findall returns non-overlapping matches, and groups change the result.The result depends on the number of capturing groups in the pattern.
docs.python.org/3.12/library/re.html — findall result depends on the number of groups.Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl .
docs.python.org/3.12/library/re.html — sub replaces the leftmost non-overlapping matches.backslashes are not handled in any special way in a string literal prefixed with 'r'
docs.python.org/3.12/library/re.html — Raw strings keep backslashes as written.it's highly recommended that you use raw strings for all but the simplest expressions.
docs.python.org/3.12/library/re.html — Raw strings are recommended for patterns.Match objects always have a boolean value of True .
docs.python.org/3.12/library/re.html — A match object is always true, so test it with if.Returns one or more subgroups of the match.
docs.python.org/3.12/library/re.html — Match.group returns subgroups.If multiple groups are present, return a list of tuples of strings matching the groups.
docs.python.org/3.12/library/re.html — findall returns tuples when several groups are present.