grep with regex for phone number

Viewed 55001

I would like to get the phone numbers from a file. I know the numbers have different forms, I can handle for a single one, but don't know how to get a uniform regex. For example

  1. xxx-xxx-xxxx

  2. (xxx)xxx-xxxx

  3. xxx xxx xxxx

  4. xxxxxxxxxx

I can only handle 1, 2, and 4 together

grep '[0-9]\{3\}[ -]\?[0-9]\{3\}[ -]\?[0-9]\{4\}' file

Is there any one single regex can handle all of these four forms?

11 Answers
grep '\(([0-9]\{3\})\|[0-9]\{3\}\)[ -]\?[0-9]\{3\}[ -]\?[0-9]\{4\}' file

Explanation:

([0-9]\{3\}) three digits inside parentheses

\| or

[0-9]\{3\} three digits not inside parens

...with grouping parentheses - \(...\) - around the alternation so the rest of the regex behaves the same no matter which alternative matches.

You can just OR (|) your regexes together -- will be more readable that way too!

My first thought is that you may find it easier to see if your candidate number matches against one of four regular expressions. That will be easier to develop/debug, especially as/when you have to handle additional formats in the future.

grep -P '[0-9]{3}-[0-9]{3}-[0-9]{3}|[0-9]{3}\ [0-9]{3}\ [0-9]{3}|[0-9]{9}|\([0-9]{3}\)[0-9]{3}-[0-9]{3}'
grep -oE '\(?\<[0-9]{3}[-) ]?[0-9]{3}[ -]?[0-9]{4}\>'

Matches all your formats.

The \< and \> word boundaries prevent matching numbers that are too long, such as 123-123-12345 or 1234-123-1234

I got this:

debian:tmp$ cat p.txt
333-444-5555
(333)333-6666
123 456 7890
1234567890
debian:tmp$ egrep '\(?[0-9]{3}[ )-]?[0-9]{3}[ -]?[0-9]{4}' p.txt
333-444-5555
(333)333-6666
123 456 7890
1234567890
debian:tmp$ egrep --version
GNU grep 2.5.3

Copyright (C) 1988, 1992-2002, 2004, 2005  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

debian:tmp$
Related