RegEx: How to Extract Phone Numbers from Text with Regular Expressions

As a data analyst or programmer, you‘ll frequently need to extract specific bits of information buried in larger strings of text. Phone numbers are a classic example. You might have a database of customer records where the phone numbers are mixed in with other contact details, or a scraped web page where the numbers appear in different formats. In these situations, regular expressions (regex) are an invaluable tool to search for, match, and extract phone numbers into a standardized format.

In this guide, we‘ll walk through how to use regex to identify and pull out all phone numbers from text strings, no matter how they‘re formatted. We‘ll cover the basics of regex syntax, share some example patterns to match different types of phone numbers, and discuss techniques to extract the data in various programming languages. By the end, you‘ll have a solid foundation to start using regex in your own data wrangling projects.

What are Regular Expressions?

Regular expressions (regex for short) are a sequence of characters that define a search pattern. When included in code or search algorithms, regular expressions can be used to find certain patterns of characters within a string, or to find and replace a character or sequence of characters within a string. They are also frequently used to validate input.

For example, the regular expression ^a...s$ means: any five letter string starting with a and ending with s.

Regex Syntax Overview

Before diving into crafting regex patterns for phone numbers, let‘s cover some regex basics. Here are the core elements of regex syntax:

  • abc…: The simplest form of pattern, which just matches the exact characters abc, etc.
  • 123…: Matches the exact digits 123, etc.
  • . (dot): Matches any single character except line break
  • []: Matches any single character within the brackets – for example [abc] matches a, b, or c
  • [^]: Matches any single character not within the brackets
  • *: Matches 0 or more of the preceding character/group
  • +: Matches 1 or more of the preceding character/group
  • ?: Matches 0 or 1 of the preceding character/group
  • {n}: Matches exactly n of the preceding character/group
  • {n,}: Matches n or more of the preceding character/group
  • {n,m}: Matches between n and m of the preceding character/group
  • (): Groups multiple characters – useful for applying quantifiers or extracting specific portions of a match
  • |: OR operator – for example, a|b matches a or b
  • ^: Beginning of a string
  • $: End of a string

You can combine any of these elements to create sophisticated patterns. For example, ^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$ is a pattern that matches email addresses.

Building Phone Number Matching Patterns

Now let‘s see how we can use these regex building blocks to create patterns that match phone numbers in a variety of formats. We‘ll start with a simple example and gradually build up to more complex patterns.

Matching 10 Digit Numbers

Let‘s say we want to find any 10 digit phone numbers in a string. Here‘s the regex pattern to do that:

\b\d{10}\b

Here‘s what each part means:

  • \b: Matches a "word boundary" – this prevents partial matches in longer strings of digits
  • \d: Matches any single digit character (0-9) – similar to [0-9]
  • {10}: Matches the preceding \d exactly 10 times

So this will match strings like 1234567890 but not 123456789 or 12345678900.

Matching Numbers with Hyphens

Phone numbers are often written with hyphens separating groups of digits, like 123-456-7890. Here‘s how we could modify our pattern to include optional hyphens:

\b\d{3}-?\d{3}-?\d{4}\b

The -? means the hyphen is optional, since the ? matches 0 or 1 of the preceding character.

Matching Numbers with Parentheses

Here‘s another common phone number format: (123) 456-7890. Let‘s further expand our regex to handle this:

\b(?:(\d{3})\s?|\d{3}-?)\d{3}-?\d{4}\b

There are a couple new elements here:

  • (?:…): Groups multiple tokens together without creating a capture group (more on captures later)
  • \s: Matches any whitespace character (spaces, tabs, line breaks)
  • |: Matches either the pattern to the left or right (parentheses or no parentheses)

Putting it All Together

Combining all these variations, here‘s a beastly pattern that will match pretty much any North American 10 digit phone number format:

\b(?:+1[-\s.]?)?(?[2-9]\d{2})?[-\s.]?\d{3}[-\s.]?\d{4}\b

Phew! This can match any of the following:

  • 1234567890
  • 123-456-7890
  • 123.456.7890
  • 123 456 7890
  • (123) 456-7890
  • +1 123 456 7890
  • and more!

Feel free to use this as a starting point, but you may need to modify it depending on your exact phone number formatting requirements. There‘s always more than one way to write a regex!

Extracting the Matched Phone Numbers

So we‘ve written a pattern that matches phone numbers, but how do we actually extract those matched numbers for further processing? The exact method depends on the programming language or tool you‘re using, but the general concept is the same.

Most regex implementations support the concept of "capture groups" – by wrapping parts of a pattern in parentheses, you can extract just those portions of the matched text. You can then access these captures by position.

For example, consider this pattern:
\b(\d{3})-(\d{3})-(\d{4})\b

This will match a phone number like 123-456-7890, and will also capture the three groups of digits separately. You could then extract those components to assemble the phone number in any format you choose.

Here‘s a quick example in Python:

import re

text = "Call me at 123-456-7890"

pattern = re.compile(r‘\b(\d{3})-(\d{3})-(\d{4})\b‘)

match = pattern.search(text)

if match:
  area_code = match.group(1) 
  first_three = match.group(2)
  last_four = match.group(3)

  full_number = f"({area_code}) {first_three}-{last_four}"
  print(full_number)  # (123) 456-7890
else:
  print("No phone number found.")

Most programming languages have similar regex handling and group capturing features. Consult the specific docs for your language or tool to see exact usage details.

Regex Testing and Validation

As you‘re crafting your regex patterns, it‘s very useful to be able to test them against real data to make sure they‘re matching correctly. There are many free online tools for interactively building and testing regex patterns – here are a few of the most popular:

These tools provide real-time visual feedback as you build your patterns and test against sample data. They also include handy reference guides and community pattern libraries you can learn from.

Regex Caveats and Edge Cases

As powerful as regex is, it‘s not a magic bullet for every text parsing problem. Crafting the right pattern can often be tricky and time-consuming, and there are some things that regex is simply not well suited for.

When it comes to matching phone numbers, here are a few gotchas to be aware of:

  • Fake or malformed numbers: Not every 10 digit number is a valid phone number. Depending on your data source, you may encounter fake numbers like 123-456-7890 that match the formatting pattern but aren‘t real, dialable numbers. Regex alone can‘t distinguish these.

  • International numbers: Once you expand beyond North American numbers, phone number formatting gets much more diverse. You may need to do additional research and modify your patterns to handle international numbers.

  • Inconsistent punctuation: While our example pattern covers the most common formats, you may encounter phone numbers using less common punctuation, like periods instead of hyphens. Decide how exhaustive you need to be in handling these edge cases.

  • Multiple numbers per string: Our examples assumed there would only be one phone number per input string, but that may not always be the case. If you need to handle multiple matches per string, you‘ll need to use global matching and capturing, or match iterators.

Conclusion

We‘ve covered a lot of ground in this guide to matching and extracting phone numbers with regular expressions. To recap, we:

  • Explained what regex is and how it can be used for pattern matching
  • Walked through the fundamental regex syntax elements
  • Built up example patterns to match 10 digit phone numbers in various formats
  • Showed how to extract matched components using capture groups
  • Discussed regex testing tools and some common pitfalls to watch out for

Regex is an indispensable part of any data wrangler‘s toolkit, but it does take some practice to master. Start with simple patterns and work your way up to more complex ones. When in doubt, sketch out the exact formatting variations you need to handle, and don‘t hesitate to hit up reference guides and community forums for help. Before long, you‘ll be slicing and dicing text data with the best of them!

Leave a Reply

Your email address will not be published. Required fields are marked *