Skip to content
Lesson 7 of 9

Step 1 of 4 · Reading · ~3 min

Learn

Real-World Python

Regular Expressions

You're cleaning a dataset and need every phone number in a document — some written 555-123-4567, others (555) 123-4567. String methods like .find() and .split() match exact text; regular expressions match patterns. Python's re module lets you describe the shape of the text you want, then search for it, extract it, validate it, or replace it.

The functions that matter

python

search, match, and fullmatch return a match object (truthy) or None — which is why if re.fullmatch(pattern, s): is the standard validation idiom.

Always write patterns as raw strings: r"\d+", never "\d+". In a normal string Python itself interprets backslashes, so "\b" becomes a backspace character before re ever sees the pattern. The r prefix hands your backslashes over intact.

The pattern language, condensed

\d  digit         \w  word char        \s  whitespace
[abc]  one of a, b, c                  [^@]  any char EXCEPT @
.   any single character (a LITERAL dot must be escaped: \.)
*   zero or more     +   one or more     ?   optional     {2,4}  two to four
^   start of string     $   end of string     (…)  capture group     a|b  either

Extract pieces with groups:

python

The traps

match is not fullmatch. re.match(r"\d+", "123abc") succeeds — it anchors the start but not the end. For validation ("is this WHOLE string an email?") use re.fullmatch, or you'll accept garbage suffixes.

. means any character. r"a.c" matches "abc" and "a@c" alike. A domain check written example.com happily accepts exampleXcom. Mean a real dot? Escape it: \..

* accepts empty. * is zero or more — [^@]* matches an empty string without complaint. When something must actually be present, that's + (one or more).

Greedy by default. .* grabs as much as possible, .*? as little as possible: re.findall(r"<.*>", "<a><b>") returns ['<a><b>'], while r"<.*?>" returns ['<a>', '<b>'].

The validation idiom

re.fullmatch plus a printed verdict is the shape you reach for whenever a whole string has to conform. Here it is on a warehouse stock code — two uppercase letters, a hyphen, then exactly four digits:

python

Three parts transfer to any pattern you write: a character class says which characters may sit in a position, a quantifier (+, {4}) says how many of them, and an escape (\.) is how you mean a literal dot instead of "any character".

Your exercise

The first input line is a count N; each of the next N lines is a candidate email. Print valid or invalid for each — lowercase, one per line, exact spelling; the grader compares your stdout against the expected text and forgives nothing but trailing whitespace at the very end. Valid means: text before the @, text after it, and a dot after the @. Two decisions settle whether you pass. Quantifier: * also matches the empty string, so a pattern built from * calls an address with nothing before the @ valid — there is a test for exactly that. Anchoring: re.match pins only the start, so trailing garbage survives it; re.fullmatch is what "the whole string must conform" means. And the first input line is the count, not a candidate.

Up nextWorking with JSONReal-World Python

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…