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.
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?
Begin: re.search() receives the pattern and the complete string.
Scan: Python examines the string from left to right.
Stop: When the first matching portion is found, scanning stops.
Return: 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
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?
Read the start: Use match.start() to identify the first character position of the match.
Read the end: Use match.end() to identify the position immediately after the final matched character.
Apply a slice: Use original_string[match.start():match.end()] to select the same range from the original string.
Compare: 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 |
Debugging Failed Searches
Calling group(), start(), or end() without checking the search result
None is not a match object and does not provide the match-object methods.
Fix:
Check whether the result is present before calling group(), start(), or end().Treating re.search() as if it returns only True or False
A successful search returns a match object containing more information than a Boolean value.
Fix:
Keep the match object when you need group(), start(), or end().Expecting re.search() and find() to report failure in the same way
The two APIs use different failure values.
Fix:
Interpret -1 as find() failure and None as re.search() failure.Using a regular expression for a simple literal search
This does not take advantage of regular-expression pattern matching.
Fix:
Use 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(), and end().
A Reliable Search Routine
Describe the safe reasoning sequence for searching a message for a pattern that might or might not occur.
Prepare: Import the re module and identify the pattern and source string.
Search: Call re.search(pattern, string).
Branch: Treat a match object as the found branch and None as the no-match branch.
Inspect: Only on the found branch, use group() for the matched text and start() or end() for its positions.
A safe search routine checks the return value before accessing match-object methods.
Essential Takeaways
- re.search() scans a string from left to right and stops at the first match.
- A found pattern produces a match object; an absent pattern produces None.
- Use group(), start(), and end() to inspect matched text and its positions.
- The start and end values follow Python's zero-based indexing and slicing convention.
- Use re.search() for patterns and find() or in for exact fixed strings.
Key Takeaways
- 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 with start() and end().
- Always check for a match before calling match-object methods.
- Use regular expressions for patterns; use find() or in for simple literal searches.