简体   繁体   中英

C# Regex Phone Number Check

I have the following to check if the phone number is in the following format (XXX) XXX-XXXX. The below code always return true. Not sure why.

   Match match = Regex.Match(input, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}");

    // Below code always return true
    if (match.Success) { ....}

The general complaint about regex patterns for phone numbers is that they require one to put in the truly optional characters as dashes and other items.

Why can't they be optional and have the pattern not care if they are there or not?

The below pattern makes dashes, periods and parenthesis optional for the user and focuses on the numbers as a result using named captures.

The pattern is commented (using the # and spans multiple lines) so use the Regex option IgnorePatternWhitespace unless one removes the comments. For that flag doesn't affect regex processing, it only allows for commenting of the pattern via the # character and line break .

string pattern = @"
^                  # From Beginning of line
(?:\(?)            # Match but don't capture optional (
(?<AreaCode>\d{3}) # 3 digit area code
(?:[\).\s]?)       # Optional ) or . or space
(?<Prefix>\d{3})   # Prefix
(?:[-\.\s]?)       # optional - or . or space
(?<Suffix>\d{4})   # Suffix
(?!\d)             # Fail if eleventh number found";

The above pattern just looks for 10 numbers and ignores any filler characters such as a ( or a dash - or a space or a tab or even a . . Examples are

(555)555-5555 (OK)
5555555555 (ok)
555 555 5555(ok)
555.555.5555 (ok)
55555555556 (not ok - match failure - too many digits)
123.456.789 (failure)

Different Variants of same pattern

Pattern without comments no longer need to use IgnorePatternWhiteSpace :

^(?:\(?)(?<AreaCode>\d{3})(?:[\).\s]?)(?<Prefix>\d{3})(?:[-\.\s]?)(?<Suffix>\d{4})(?!\d)

Pattern when not using Named Captures

^(?:\(?)(\d{3})(?:[\).\s]?)(\d{3})(?:[-\.\s]?)(\d{4})(?!\d)

Pattern if ExplicitCapture option is used

^\(?(?<AreaCode>\d{3})[\).\s]?(?<Prefix>\d{3})[-\.\s](?<Suffix>\d{4})(?!\d)

It doesn't always match, but it will match any string that contains three digits, followed by a hyphen, followed by four more digits. It will also match if there's something that looks like an area code on the front of that. So this is valid according to your regex:

%%%%%%%%%%%%%%(999)123-4567%%%%%%%%%%%%%%%%%

To validate that the string contains a phone number and nothing else , you need to add anchors at the beginning and end of the regex:

@"^((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}$"

Alan Moore did a good explaining what your exp is actually doing. +1

If you want to match exactly "(XXX) XXX-XXXX" and absolutely nothing else, then what you want is

@"^\(\d{3}\) \d{3}-\d{4}$"

Here is the C# code I use. It is designed to get all phone numbers from a page of text. It works for the following patters: 0123456789, 012-345-6789, (012)-345-6789, (012)3456789 012 3456789, 012 345 6789, 012 345-6789, (012) 345-6789, 012.345.6789

List<string> phoneList = new List<string>();
Regex rg = new Regex(@"\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})");
MatchCollection m = rg.Matches(html);
foreach (Match g in m)
{
    if (g.Groups[0].Value.Length > 0)
        phoneList.Add(g.Groups[0].Value);
}

none of the comments above takes care of international numbers like +33 6 87 17 00 11 (which is a valid phone number for France for example). I would do it in a two-step approach: 1. Remove all characters that are not numbers or '+' character 2. Check the + sign is at the beginning or not there. Check length (this can be very hard as it depends on local country number schemes). Now if your number starts with +1 or you are sure the user is in USA, then you can apply the comments above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM