Common Regex Patterns for Email and Phone Numbers
re.search() returns a match object when a pattern is found, or None when no match exists.
Try it: Regular expressions: a backtracking matcher
How Python's re module matches a pattern: it tries each start position, matches tokens one by one, lets greedy quantifiers take as much as possible and give it back when the rest fails (lazy ones take as little as possible), tries alternatives in order and records groups.
How it works
- search tries start positions 0, 1, 2 …; match tries only position 0; findall collects every non-overlapping match.
- Tokens are matched left to right: literals, ., classes like [a-c] and \d, and zero-width anchors ^, \$, \b.
- A greedy quantifier (* + ? {m,n}) takes as many repetitions as it can, then backtracks one at a time; a lazy one (*? +? ??) takes as few as possible and grows only when needed.
- Alternatives in a | b are tried in order; the first that lets the whole pattern match wins.
- Parentheses capture the text their part matched; captures are undone when the matcher backtracks past them.
Default run (63 steps): re.search('(\\w+)@(\\w+)\\.com', 'mail bo@ikb.com now'): try each start position until one matches. … re.search('(\\w+)@(\\w+)\\.com', 'mail bo@ikb.com now') → <re.Match object; span=(5, 15), match='bo@ikb.com'>
Simplified: A subset of re: no flags, lookarounds, backreferences, named groups or possessive quantifiers; pattern and text up to 24 printable ASCII characters. The trace stops after 1900 attempts ("too many steps") where real Python would keep backtracking.
Loading the simulation…
From Text to Search Result
When a program needs to locate an email-like or phone-like portion of text, the central question is not only whether the text is present. The program may also need to know exactly what was found and where it appeared. Python's re module provides regular-expression tools for this kind of search. Its re.search() function scans a string for a pattern and produces one of two outcomes: a match object when the pattern is found, or None when no match exists.
A successful search does not return only True or the matched text. It returns a match object containing information about the match.
The Left-to-Right Scan
When you call re.search(pattern, string), Python scans the string from left to right. As soon as it finds text that satisfies the pattern, the search stops and returns a match object describing that first match. If the pattern never appears, the scan finishes without finding a match and re.search() returns None.
Finding a Pattern Inside a Message
Suppose a message contains ordinary text followed by a portion that satisfies the pattern supplied to re.search(). What happens during the search?
- 1Begin
re.search()receives the pattern and the complete string. - 2Scan
Python examines the string from left to right.
- 3Stop
When the first matching portion is found, scanning stops.
- 4Return
The function returns a match object describing the portion that matched.
The result is a match object rather than a simple Boolean value.
Two Possible Return Values
The result of re.search() determines the next step in your program. If a match exists, the result is a match object and can be inspected. If no match exists, the result is None. None is falsy, so the result can be tested directly in an if condition. The matched object is truthy, allowing the same condition to represent the question: was a match found?
What do you think happens?
A search finds no portion of the string that satisfies its pattern. What does re.search() return?
Reveal answer
None
re.search() returns None when no match exists. Because None is falsy, a conditional test can use that result to choose the no-match path.
Reading Match Details
A match object stores several useful details. The group() method returns the matched text. The start() method returns the index where the match begins, and the end() method returns the index immediately after the final matched character. The original string is also part of the match object's information.
Connecting Indices to the Matched Text
A match object reports a starting index and an ending index for a matched portion of a string. How can you verify the exact characters included?
- 1Read the start
Use
match.start()to identify the first character position of the match. - 2Read the end
Use
match.end()to identify the position immediately after the final matched character. - 3Apply a slice
Use
original_string[match.start():match.end()] to select the same range from the original string. - 4Compare
The slice gives the same matched text returned by
match.group().
The match indices follow Python's zero-based indexing and slice convention.
Patterns Versus Literal Text
The re module is most useful when the search condition describes a pattern rather than one exact fixed string. The source material identifies examples such as finding any digit, any word character, a repeating pattern, or one of several alternatives. These are situations where a regular expression can express a broader condition. For an exact literal such as From:, using re.search() does not use the distinctive power of regular expressions.
| Situation | Suitable approach | Failure result |
|---|---|---|
| Search for an exact fixed string such as From: | find() or the in operator | find() returns -1 when absent |
| Search for a pattern involving digits, word characters, repetition, or alternatives | re.search() | re.search() returns None when absent |
The choice depends on whether the condition is a literal string or a broader pattern.
Debugging Failed Searches
Common mistake Calling group(), start(), or end() without checking the search result
What it looks likeA search finds no match, so its result is None. Calling a match-object method on that result causes an AttributeError.
Why it failsNone is not a match object and does not provide the match-object methods.
Do this insteadCheck whether the result is present before calling group(), start(), or end().
Common mistake Treating re.search() as if it returns only True or False
What it looks likeA condition confirms that a match exists, but the program still needs the matched text or its location.
Why it failsA successful search returns a match object containing more information than a Boolean value.
Do this insteadKeep the match object when you need group(), start(), or end().
Common mistake Expecting re.search() and find() to report failure in the same way
What it looks likeA missing literal gives -1 from find(), while a missing regular-expression match gives None from re.search().
Why it failsThe two APIs use different failure values.
Do this insteadInterpret -1 as find() failure and None as re.search() failure.
Common mistake Using a regular expression for a simple literal search
What it looks likeSearching for the exact text From: with re.search() instead of using find() or in.
Why it failsThis does not take advantage of regular-expression pattern matching.
Do this insteadUse simpler string methods for exact fixed text.
Separate the two questions in your reasoning: first ask whether the result is a match object, and only then ask what text or positions the object contains. This makes None returns a normal branch of control rather than an unexpected error.
Apply the Decision
For each situation, decide whether re.search(), find(), or in is the better starting point. Then state what result you must check before extracting match details: an exact search for From:, a search for any digit, and a search for a repeating pattern.
Hints
- Use simpler string methods for an exact fixed string.
- Use
re.search()when the condition describes a pattern. - Only a match object has
group(),start(), andend().
A Reliable Search Routine
Describe the safe reasoning sequence for searching a message for a pattern that might or might not occur.
- 1Prepare
Import the re module and identify the pattern and source string.
- 2Search
Call
re.search(pattern, string). - 3Branch
Treat a match object as the found branch and None as the no-match branch.
- 4Inspect
Only on the found branch, use
group()for the matched text andstart()orend()for its positions.
A safe search routine checks the return value before accessing match-object methods.
Essential Takeaways
- 1
re.search()scans a string from left to right and stops at the first match. - 2A found pattern produces a match object; an absent pattern produces None.
- 3Use
group(),start(), andend()to inspect matched text and its positions. - 4The start and end values follow Python's zero-based indexing and slicing convention.
- 5Use
re.search()for patterns andfind()or in for exact fixed strings.
At a glance
re.search()returns a match object when its pattern is found and None otherwise.- Python scans from left to right and returns the first matching portion.
- A match object exposes the matched text with
group()and its boundaries withstart()andend(). - Always check for a match before calling match-object methods.
- Use regular expressions for patterns; use
find()or in for simple literal searches.