如何使用正则表达式验证电话号码

How to validate phone numbers using regex

提问人: 提问时间:9/24/2008 最后编辑:7 revs, 6 users 54%Nicholas Trandem 更新时间:7/29/2023 访问量:1190203

问:

我正在尝试将一个全面的正则表达式放在一起来验证电话号码。理想情况下,它将处理国际格式,但它必须处理美国格式,包括以下内容:

  • 1-234-567-8901
  • 1-234-567-8901 x1234
  • 1-234-567-8901 ext1234
  • 1 (234) 567-8901
  • 1.234.567.8901
  • 1/234/567/8901
  • 12345678901

我会用我目前的尝试来回答,但我希望有人有更好和/或更优雅的东西。

正则表达式 验证 电话号码

评论

2赞 aliteralmind 4/10/2014
此答案已添加到 Stack Overflow 正则表达式常见问题解答的“常见验证任务”下。
0赞 Lewis Cianci 7/25/2022
不幸的是,转到该页面并搜索“常见验证任务”不会产生任何结果......
0赞 Guildenstern 3/29/2023
这是正则表达式任务吗?
0赞 Toothpick Anemone 4/14/2023
在某些情况下,这是一个 XY 问题。您要求一个谓词,如果电话号码有效,则返回该谓词,但您实际上只是想要一个正确的电话号码。对于任何试图将最终用户输入的电话号码清理到网页或手机应用程序中的人,我建议只需使用 4 或 5 行代码,一次从左到右一个字符并丢弃所有非数字。 成为。删除所有非数字后,您可以在适当的位置插入 (点 )、插入 (连字符 ) 或斜杠。True(303)873-99193038739919.-

答:

11赞 Nicholas Trandem #1

这是我迄今为止最好的尝试。它处理上述格式,但我敢肯定我错过了其他一些可能的格式。

^\d?(?:(?:[\+]?(?:[\d]{1,3}(?:[ ]+|[\-.])))?[(]?(?:[\d]{3})[\-/)]?(?:[ ]+)?)?(?:[a-zA-Z2-9][a-zA-Z0-9 \-.]{6,})(?:(?:[ ]+|[xX]|(i:ext[\.]?)){1,2}(?:[\d]{1,5}))?$

评论

0赞 KdPisda 1/29/2021
像魅力一样工作!感谢分享
15赞 Rob Wells #2

你看过RegExLib吗?

输入美国电话号码会带来很多可能性。

评论

3赞 Tom Lord 10/26/2016
这看起来像是将晦涩难懂的错误集成到代码中的好方法。
0赞 mickmackusa 8/1/2020
应避免仅链接的答案,因为它们将来可能会中断并使帖子变得无用。静态解决方案对于维持答案的价值始终是必要的。如果您想推荐一个超链接,请将其添加为问题下的注释。
331赞 2 revsfatcat1111 #3

事实证明,至少在北美,有一个规范,称为 NANP

您需要准确指定所需的内容。什么是法定分隔符?空格、破折号和句点?不允许使用分隔符?可以混合使用分隔符(例如,+0.111-222.3333)吗?如何处理扩展(例如,111-222-3333 x 44444)?像 911 这样的特殊号码呢?区号是可选的还是必需的?

下面是 7 位或 10 位数字的正则表达式,允许扩展名,分隔符为空格、破折号或句点:

^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$

评论

7赞 aarona 5/4/2010
这里没有扩展部分(我让我的用户在单独的字段中输入 ext):^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})$
20赞 Brian Armstrong 9/8/2010
这是一个仅匹配 10 位电话号码的版本(而不是像 843-1212 这样的 7 位数字):/(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})/
11赞 Brooke. 1/9/2011
10 位数字接受区号周围的 (),并且不允许在 1 之前作为国家/地区代码(?:(?:(\s*\(?([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\)?\s*(?:[.-]\s*)?)([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})
6赞 Justin R. 3/29/2013
@StevenSoroka在过去的两年里,我的办公桌上一直放着杰弗里·弗里德尔(Jeffrey Friedl)的书,因为正则表达是我工作的重要组成部分。真正理解正则表达式需要很长时间。有时,本网站的读者只是在寻找现有的解决方案,而不是编写自己的解决方案,尤其是在有很多极端情况的领域,例如电话号码表示。
7赞 Steven Soroka 4/6/2013
@fatcat1111我理解这一点,但这里的大多数回复都是“我也是”类型的一次性正则表达式,可能不适合你的任何极端情况。然后,这些最终会出现在我尝试使用的所有网站上,我无法输入我的邮政编码、电话号码或电子邮件地址,因为有人使用了半生不熟的正则表达式(例如:+ 是电子邮件地址中的有效字符)。此页面上的最佳响应将用户指向库,而不是餐巾纸潦草的正则表达式。
548赞 3 revs, 3 users 87%scunliffe #4

Better option... just strip all non-digit characters on input (except 'x' and leading '+' signs), taking care because of the British tendency to write numbers in the non-standard form when asked to use the international prefix (in that specific case, you should discard the entirely).+44 (0) ...(0)

Then, you end up with values like:

 12345678901
 12345678901x1234
 345678901x1234
 12344678901
 12345678901
 12345678901
 12345678901
 +4112345678
 +441234567890

Then when you display, reformat to your hearts content. e.g.

  1 (234) 567-8901
  1 (234) 567-8901 x1234

评论

42赞 Daniel Earwicker 7/21/2009
The formatting code is going to be a waste of time if the numbers are allowed to come from outside the US.
29赞 Hugh Jeffner 7/29/2010
This is good and all, but it doesn't validate what was entered was actually a phone number. For example, what if the user doesn't enter the requisite 10 digits? This should be combined with good regex validation.
145赞 PlexQ 3/31/2012
Considering the question was about validation - this is a really really bad answer.
17赞 scunliffe 3/31/2012
@PlexQ I disagree. The original problem is trying to handle phone number validation because it was trying to handle all the possible formatting options. Rather than try to solve all that, take the input and "pre-strip" it of all formatting fluff until you have just the "number". Doing this solves 2 problems - testing the result is now easy and you can now ensure that values rendered back out for display can all be formatted consistently. The first comment on this answer about the "Complicator's Gloves" is a good read... sometimes the answer to a problem is to approach it differently.
46赞 jlars62 6/20/2014
How the hell is this such a highly voted answer? This doesn't validate anything. What's worse is all the other phone number validation questions reference this one...
4赞 Joe Phillips #5

I work for a market research company and we have to filter these types of input alllll the time. You're complicating it too much. Just strip the non-alphanumeric chars, and see if there's an extension.

For further analysis you can subscribe to one of many providers that will give you access to a database of valid numbers as well as tell you if they're landlines or mobiles, disconnected, etc. It costs money.

评论

0赞 PlexQ 3/31/2012
Validation? 123%$)*%()$*()#456*()*$#(*(#$@8908 would match your proposed solution.
1赞 ReactiveRaven 4/29/2012
@PlexQ 555-123-1234, 07777777777, 90210, 01/01/1901 - users are inventive in ramming garbage through validation. Better to not tic off the ones who genuinely do have some odd data by using overly restrictive validation and telling them they're wrong.
-1赞 3 revs, 3 users 50%Kibbee #6

If at all possible, I would recommend to have four separate fields—Area Code, 3-digit prefix, 4 digit part, extension—so that the user can input each part of the address separately, and you can verify each piece individually. That way you can not only make verification much easier, you can store your phone numbers in a more consistent format in the database.

评论

0赞 uliwitness 4/1/2014
However, if you decide to go this route, keep in mind that this will not work outside the US. No way to enter a country extension, and e.g. Germany has variable-length area codes (anywhere from 2-4 digits, plus a leading zero if you're dialing from within Germany, which is left out if you have a country code before it).
9赞 2 revsAdam Davis #7

You'll have a hard time dealing with international numbers with a single/simple regex, see this post on the difficulties of international (and even north american) phone numbers.

You'll want to parse the first few digits to determine what the country code is, then act differently based on the country.

Beyond that - the list you gave does not include another common US format - leaving off the initial 1. Most cell phones in the US don't require it, and it'll start to baffle the younger generation unless they've dialed internationally.

You've correctly identified that it's a tricky problem...

-Adam

评论

0赞 Eric Hodonsky 3/30/2017
Not an offered solution. IT IS POSSIBLE. Just because it's tricky or complex doesn't mean you should just throw your arms up.
6赞 Jon 'links in bio' Ericson #8

I believe the Number::Phone::US and Regexp::Common (particularly the source of Regexp::Common::URI::RFC2806) Perl modules could help.

The question should probably be specified in a bit more detail to explain the purpose of validating the numbers. For instance, 911 is a valid number in the US, but 911x isn't for any value of x. That's so that the phone company can calculate when you are done dialing. There are several variations on this issue. But your regex doesn't check the area code portion, so that doesn't seem to be a concern.

Like validating email addresses, even if you have a valid result you can't know if it's assigned to someone until you try it.

If you are trying to validate user input, why not normalize the result and be done with it? If the user puts in a number you can't recognize as a valid number, either save it as inputted or strip out undailable characters. The Number::Phone::Normalize Perl module could be a source of inspiration.

评论

0赞 Blank 7/11/2012
I'm going to go out on a limb here and say that allowing 911 as a phone number is probably a bad idea in almost all applications of this regex. Good catch though.
66赞 2 revsindiv #9

Although the answer to strip all whitespace is neat, it doesn't really solve the problem that's posed, which is to find a regex. Take, for instance, my test script that downloads a web page and extracts all phone numbers using the regex. Since you'd need a regex anyway, you might as well have the regex do all the work. I came up with this:

1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?

Here's a perl script to test it. When you match, $1 contains the area code, $2 and $3 contain the phone number, and $5 contains the extension. My test script downloads a file from the internet and prints all the phone numbers in it.

#!/usr/bin/perl

my $us_phone_regex =
        '1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?';


my @tests =
(
"1-234-567-8901",
"1-234-567-8901 x1234",
"1-234-567-8901 ext1234",
"1 (234) 567-8901",
"1.234.567.8901",
"1/234/567/8901",
"12345678901",
"not a phone number"
);

foreach my $num (@tests)
{
        if( $num =~ m/$us_phone_regex/ )
        {
                print "match [$1-$2-$3]\n" if not defined $4;
                print "match [$1-$2-$3 $5]\n" if defined $4;
        }
        else
        {
                print "no match [$num]\n";
        }
}

#
# Extract all phone numbers from an arbitrary file.
#
my $external_filename =
        'http://web.textfiles.com/ezines/PHREAKSANDGEEKS/PnG-spring05.txt';
my @external_file = `curl $external_filename`;
foreach my $line (@external_file)
{
        if( $line =~ m/$us_phone_regex/ )
        {
                print "match $1 $2 $3\n";
        }
}

Edit:

You can change \W* to \s*\W?\s* in the regex to tighten it up a bit. I wasn't thinking of the regex in terms of, say, validating user input on a form when I wrote it, but this change makes it possible to use the regex for that purpose.

'1?\s*\W?\s*([2-9][0-8][0-9])\s*\W?\s*([2-9][0-9]{2})\s*\W?\s*([0-9]{4})(\se?x?t?(\d*))?';

评论

2赞 SooDesuNe 2/21/2013
FYI the regex also matches: which would be a pretty common typo. The match groups get skewed too: rubular.com/r/TaTP0mHL5c(4570457-6789
0赞 btown 3/24/2017
@SooDesuNe Prepending (with multiline flag on) avoids the general problem, by ensuring it's not immediately preceded by something numeric.(^|[^\d\n])
0赞 Ben Wheeler 3/26/2020
Note that this is North America-centric -- it misses "44 7911 123456"
2赞 piCookie #10

My inclination is to agree that stripping non-digits and just accepting what's there is best. Maybe to ensure at least a couple digits are present, although that does prohibit something like an alphabetic phone number "ASK-JAKE" for example.

A couple simple perl expressions might be:

@f = /(\d+)/g;
tr/0-9//dc;

Use the first one to keep the digit groups together, which may give formatting clues. Use the second one to trivially toss all non-digits.

Is it a worry that there may need to be a pause and then more keys entered? Or something like 555-1212 (wait for the beep) 123?

11赞 3 revs, 3 users 65%ron0 #11

If you're talking about form validation, the regexp to validate correct meaning as well as correct data is going to be extremely complex because of varying country and provider standards. It will also be hard to keep up to date.

I interpret the question as looking for a broadly valid pattern, which may not be internally consistent - for example having a valid set of numbers, but not validating that the trunk-line, exchange, etc. to the valid pattern for the country code prefix.

North America is straightforward, and for international I prefer to use an 'idiomatic' pattern which covers the ways in which people specify and remember their numbers:

^((((\(\d{3}\))|(\d{3}-))\d{3}-\d{4})|(\+?\d{2}((-| )\d{1,8}){1,5}))(( x| ext)\d{1,5}){0,1}$

The North American pattern makes sure that if one parenthesis is included both are. The international accounts for an optional initial '+' and country code. After that, you're in the idiom. Valid matches would be:

  • (xxx)xxx-xxxx
  • (xxx)-xxx-xxxx
  • (xxx)xxx-xxxx x123
  • 12 1234 123 1 x1111
  • 12 12 12 12 12
  • 12 1 1234 123456 x12345
  • +12 1234 1234
  • +12 12 12 1234
  • +12 1234 5678
  • +12 12345678

This may be biased as my experience is limited to North America, Europe and a small bit of Asia.

评论

0赞 Jannis 10/18/2010
I've been trying to implement the above in my javascript validation script but I keep getting an error. Any ideas on what I'm doing wrong?invalid quantifier
0赞 rupps 4/20/2015
I'd add the trivial case where the phone is specified without symbols but maybe spaces and country code, in Europe is typical for local and mobile numbers: 676412342, 676 46 32 12, 676 463 212
3赞 3 revs, 3 users 43%Keith Wiggans #12

I was struggling with the same issue, trying to make my application future proof, but these guys got me going in the right direction. I'm not actually checking the number itself to see if it works or not, I'm just trying to make sure that a series of numbers was entered that may or may not have an extension.

Worst case scenario if the user had to pull an unformatted number from the XML file, they would still just type the numbers into the phone's numberpad , no real reason to keep it pretty. That kind of RegEx would come out something like this for me:012345678x5

\d+ ?\w{0,9} ?\d+
  • 01234467 extension 123456
  • 01234567x123456
  • 01234567890
5赞 rooskie #13

Do a replace on formatting characters, then check the remaining for phone validity. In PHP,

 $replace = array( ' ', '-', '/', '(', ')', ',', '.' ); //etc; as needed
 preg_match( '/1?[0-9]{10}((ext|x)[0-9]{1,4})?/i', str_replace( $replace, '', $phone_num );

Breaking a complex regexp like this can be just as effective, but much more simple.

332赞 4 revs, 4 users 71%Dave Kirby #14
.*

If the users want to give you their phone numbers, then trust them to get it right. If they do not want to give it to you then forcing them to enter a valid number will either send them to a competitor's site or make them enter a random string that fits your regex. I might even be tempted to look up the number of a premium rate horoscope hotline and enter that instead.

I would also consider any of the following as valid entries on a web site:

"123 456 7890 until 6pm, then 098 765 4321"  
"123 456 7890 or try my mobile on 098 765 4321"  
"ex-directory - mind your own business"

评论

243赞 Pointy 11/11/2010
I agree with the sentiment here, but sometimes it's nice to perform validation when the phone number is actually going to be used for something important in the interest of the user. Best example here is credit card authorization for a purchase. If the phone number is wrong, the auth might fail.
64赞 Joel McBeth 12/7/2010
If the user doesn't want to enter his phone number you can just allow the field to be optional, but is it to much to ask the user to enter a valid phone number if they are going to enter one?
13赞 Ben McIntyre 2/23/2011
Also a role of validation is simply to remind people to add area codes etc that they might not otherwise remember to add, but which cannot possibly be guessed after the fact.
37赞 Alex B 11/16/2012
@Pointy But regex validation won't help you. The one and the only way to actually validate if the phone number is correct is to actually send a message to it (in case of mobile) AND make sure the user confirms using some kind of verification code. This is what you do when the number correctness is important. Everything else is just for user's convenience to protect against some (but not all) typos and does not validate anything.
16赞 Aaron Newton 9/19/2013
Cool. My phone number is 1' OR 1=1 -- PWNED. See xkcd.com/327 and owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)
34赞 2 revsArtjom Kurapov #15

I wrote simpliest (although i didn't need dot in it).

^([0-9\(\)\/\+ \-]*)$

As mentioned below, it checks only for characters, not its structure/order

评论

41赞 Steven Soroka 3/28/2013
this validates tons of numbers that are technically invalid. like, "-- +()()())())))". Learn to read regular expressions so you can understand what you're doing.
4赞 happyhardik 8/24/2013
@StevenSoroka technically it may allow lot of invalid cases, but when we think about just helping the user out to avoid common mistakes with the simplest possible solution, this is the way to go :)
2赞 Wasim A. 9/16/2013
this also matching white space, empty line
1赞 dijipiji 2/4/2014
@HappyHardik. Indeed. Simple and powerful, for basic validation let the user type more than one dot, dash, bracket or plus.
1赞 Stelios Voskos 7/29/2015
Just used it and it's wrong in many aspects. For example, a UK phone number may begin with +44, or a phone nuber may have (0) inside it. But this is not valid according to your regular expression. I would recommend @Ismael Miguel's answer. It works just fine and I would recommend you to revise your answer.
23赞 2 revs, 2 users 67%Ben Clifford #16

Note that stripping characters does not work for a style of writing UK numbers that is common: which means dial either the international number:

or in the UK dial
()+44 (0) 1234 567890+44123456789001234567890

评论

0赞 arekolek 8/18/2020
See also International notation of UK numbers
3赞 2 revs, 2 users 67%Chris #17

I found this to be something interesting. I have not tested it but it looks as if it would work

<?php
/*
string validate_telephone_number (string $number, array $formats)
*/

function validate_telephone_number($number, $formats)
{
$format = trim(ereg_replace("[0-9]", "#", $number));

return (in_array($format, $formats)) ? true : false;
}

/* Usage Examples */

// List of possible formats: You can add new formats or modify the existing ones

$formats = array('###-###-####', '####-###-###',
                 '(###) ###-###', '####-####-####',
                 '##-###-####-####', '####-####', '###-###-###',
                 '#####-###-###', '##########');

$number = '08008-555-555';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '123-555-555';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '1800-1234-5678';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '(800) 555-123';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '1234567890';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}
?>

评论

4赞 Alastair Irvine 9/30/2013
Your message seems to indicate that you didn't write this code. Would you mind citing a source, please?
0赞 James Paterson 1/12/2016
bitrepository.com/how-to-validate-a-telephone-number.html looks to be the source.
2赞 Ian #18
    pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$" 
    validateat="onsubmit"

Must end with a digit, can begin with ( or + or a digit, and may contain + - ( or )

10赞 mindplay.dk #19

My gut feeling is reinforced by the amount of replies to this topic - that there is a virtually infinite number of solutions to this problem, none of which are going to be elegant.

Honestly, I would recommend you don't try to validate phone numbers. Even if you could write a big, hairy validator that would allow all the different legitimate formats, it would end up allowing pretty much anything even remotely resembling a phone number in the first place.

In my opinion, the most elegant solution is to validate a minimum length, nothing more.

评论

0赞 Christopher King 1/17/2014
After trying a number of these and going through the existing data and feedback from users i would tend to agree...
0赞 zfj3ub94rf576hc4eegm 4/24/2020
Sometimes you need to do validation though. If I'm sending out confirmation codes I can't just send a code to any random garbage a spammer has input in the field. I want to make sure the number is probably a phone number before wasting resources messaging it.
2赞 3 revs, 3 users 87%Lajos Arpad #20

For anyone interested in doing something similar with Irish mobile phone numbers, here's a straightforward way of accomplishing it:

http://ilovenicii.com/?p=87

PHP


<?php
$pattern = "/^(083|086|085|086|087)\d{7}$/";
$phone = "087343266";

if (preg_match($pattern,$phone)) echo "Match";
else echo "Not match";

There is also a JQuery solution on that link.

EDIT:

jQuery solution:

    $(function(){
    //original field values
    var field_values = {
            //id        :  value
            'url'       : 'url',
            'yourname'  : 'yourname',
            'email'     : 'email',
            'phone'     : 'phone'
    };

        var url =$("input#url").val();
        var yourname =$("input#yourname").val();
        var email =$("input#email").val();
        var phone =$("input#phone").val();


    //inputfocus
    $('input#url').inputfocus({ value: field_values['url'] });
    $('input#yourname').inputfocus({ value: field_values['yourname'] });
    $('input#email').inputfocus({ value: field_values['email'] }); 
    $('input#phone').inputfocus({ value: field_values['phone'] });



    //reset progress bar
    $('#progress').css('width','0');
    $('#progress_text').html('0% Complete');

    //first_step
    $('form').submit(function(){ return false; });
    $('#submit_first').click(function(){
        //remove classes
        $('#first_step input').removeClass('error').removeClass('valid');

        //ckeck if inputs aren't empty
        var fields = $('#first_step input[type=text]');
        var error = 0;
        fields.each(function(){
            var value = $(this).val();
            if( value.length<12 || value==field_values[$(this).attr('id')] ) {
                $(this).addClass('error');
                $(this).effect("shake", { times:3 }, 50);

                error++;
            } else {
                $(this).addClass('valid');
            }
        });        

        if(!error) {
            if( $('#password').val() != $('#cpassword').val() ) {
                    $('#first_step input[type=password]').each(function(){
                        $(this).removeClass('valid').addClass('error');
                        $(this).effect("shake", { times:3 }, 50);
                    });

                    return false;
            } else {   
                //update progress bar
                $('#progress_text').html('33% Complete');
                $('#progress').css('width','113px');

                //slide steps
                $('#first_step').slideUp();
                $('#second_step').slideDown();     
            }               
        } else return false;
    });

    //second section
    $('#submit_second').click(function(){
        //remove classes
        $('#second_step input').removeClass('error').removeClass('valid');

        var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;  
        var fields = $('#second_step input[type=text]');
        var error = 0;
        fields.each(function(){
            var value = $(this).val();
            if( value.length<1 || value==field_values[$(this).attr('id')] || ( $(this).attr('id')=='email' && !emailPattern.test(value) ) ) {
                $(this).addClass('error');
                $(this).effect("shake", { times:3 }, 50);

                error++;
            } else {
                $(this).addClass('valid');
            }


        function validatePhone(phone) {
        var a = document.getElementById(phone).value;
        var filter = /^[0-9-+]+$/;
            if (filter.test(a)) {
                return true;
            }
            else {
                return false;
            }
        }

        $('#phone').blur(function(e) {
            if (validatePhone('txtPhone')) {
                $('#spnPhoneStatus').html('Valid');
                $('#spnPhoneStatus').css('color', 'green');
            }
            else {
                $('#spnPhoneStatus').html('Invalid');
            $('#spnPhoneStatus').css('color', 'red');
            }
        });

     });

        if(!error) {
                //update progress bar
                $('#progress_text').html('66% Complete');
                $('#progress').css('width','226px');

                //slide steps
                $('#second_step').slideUp();
                $('#fourth_step').slideDown();     
        } else return false;

    });


    $('#submit_second').click(function(){
        //update progress bar
        $('#progress_text').html('100% Complete');
        $('#progress').css('width','339px');

        //prepare the fourth step
        var fields = new Array(
            $('#url').val(),
            $('#yourname').val(),
            $('#email').val(),
            $('#phone').val()

        );
        var tr = $('#fourth_step tr');
        tr.each(function(){
            //alert( fields[$(this).index()] )
            $(this).children('td:nth-child(2)').html(fields[$(this).index()]);
        });

        //slide steps
        $('#third_step').slideUp();
        $('#fourth_step').slideDown();            
    });


    $('#submit_fourth').click(function(){

        url =$("input#url").val();
        yourname =$("input#yourname").val();
        email =$("input#email").val();
        phone =$("input#phone").val();

        //send information to server
        var dataString = 'url='+ url + '&yourname=' + yourname + '&email=' + email + '&phone=' + phone;  



        alert (dataString);//return false;  
            $.ajax({  
                type: "POST",  
                url: "http://clients.socialnetworkingsolutions.com/infobox/contact/",  
                data: "url="+url+"&yourname="+yourname+"&email="+email+'&phone=' + phone,
                cache: false,
                success: function(data) {  
                    console.log("form submitted");
                    alert("success");
                }
                });  
        return false;

   });


    //back button
    $('.back').click(function(){
        var container = $(this).parent('div'),
        previous  = container.prev();

        switch(previous.attr('id')) {
            case 'first_step' : $('#progress_text').html('0% Complete');
                  $('#progress').css('width','0px');
                       break;
            case 'second_step': $('#progress_text').html('33% Complete');
                  $('#progress').css('width','113px');
                       break;

            case 'third_step' : $('#progress_text').html('66% Complete');
                  $('#progress').css('width','226px');
                       break;

        default: break;
    }

    $(container).slideUp();
    $(previous).slideDown();
});


});

Source.

3赞 Abe Miessler #21

You would probably be better off using a Masked Input for this. That way users can ONLY enter numbers and you can format however you see fit. I'm not sure if this is for a web application, but if it is there is a very click jQuery plugin that offers some options for doing this.

http://digitalbush.com/projects/masked-input-plugin/

They even go over how to mask phone number inputs in their tutorial.

11赞 3 revs, 3 users 75%GaiusSensei #22

This is a simple Regular Expression pattern for Philippine Mobile Phone Numbers:

((\+[0-9]{2})|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}

or

((\+63)|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}

will match these:

+63.917.123.4567  
+63-917-123-4567  
+63 917 123 4567  
+639171234567  
09171234567  

The first one will match ANY two digit country code, while the second one will match the Philippine country code exclusively.

评论

0赞 stormwild 2/26/2014
Thanks. How about landline numbers with area code such as 028231234? I'm wondering if area codes are only 2-3 digit numbers and are they always preceded by 0?
0赞 Shankar S Bavan 6/24/2022
how to validate for canada
15赞 3 revs, 3 users 92%ReactiveRaven #23

My attempt at an unrestrictive regex:

/^[+#*\(\)\[\]]*([0-9][ ext+-pw#*\(\)\[\]]*){6,45}$/

Accepts:

+(01) 123 (456) 789 ext555
123456
*44 123-456-789 [321]
123456
123456789012345678901234567890123456789012345
*****++[](][((( 123456tteexxttppww

Rejects:

mob 07777 777777
1234 567 890 after 5pm
john smith
(empty)
1234567890123456789012345678901234567890123456
911

It is up to you to sanitize it for display. After validating it could be a number though.

3赞 Richard Ayotte #24

Here's one that works well in JavaScript. It's in a string because that's what the Dojo widget was expecting.

It matches a 10 digit North America NANP number with optional extension. Spaces, dashes and periods are accepted delimiters.

"^(\\(?\\d\\d\\d\\)?)( |-|\\.)?\\d\\d\\d( |-|\\.)?\\d{4,4}(( |-|\\.)?[ext\\.]+ ?\\d+)?$"
22赞 2 revs, 2 users 74%Steve #25

If you just want to verify you don't have random garbage in the field (i.e., from form spammers) this regex should do nicely:

^[0-9+\(\)#\.\s\/ext-]+$

Note that it doesn't have any special rules for how many digits, or what numbers are valid in those digits, it just verifies that only digits, parenthesis, dashes, plus, space, pound, asterisk, period, comma, or the letters , , are present.ext

It should be compatible with international numbers and localization formats. Do you foresee any need to allow square, curly, or angled brackets for some regions? (currently they aren't included).

If you want to maintain per digit rules (such as in US Area Codes and Prefixes (exchange codes) must fall in the range of 200-999) well, good luck to you. Maintaining a complex rule-set which could be outdated at any point in the future by any country in the world does not sound fun.

And while stripping all/most non-numeric characters may work well on the server side (especially if you are planning on passing these values to a dialer), you may not want to thrash the user's input during validation, particularly if you want them to make corrections in another field.

1赞 4 revsDroogans #26

I wouldn't recomend using a regex for this.

Like the top answer, strip all the ugliness from the phone number, so that you're left with a string of numeric characters, with an , if extensions are provided.'x'

In Python:

Note: comes from a text file that you can grab from on the web.BAD_AREA_CODES

BAD_AREA_CODES = open('badareacodes.txt', 'r').read().split('\n')

def is_valid_phone(phone_number, country_code='US'):
    """for now, only US codes are handled"""
    if country_code:
        country_code = country_code.upper()

    #drop everything except 0-9 and 'x'
    phone_number = filter(lambda n: n.isdigit() or n == 'x', phone_number)

    ext = None
    check_ext = phone_number.split('x')
    if len(check_ext) > 1:
        #there's an extension. Check for errors.
        if len(check_ext) > 2:
            return False
        phone_number, ext = check_ext

    #we only accept 10 digit phone numbers.
    if len(phone_number) == 11 and phone_number[0] == '1':
        #international code
        phone_number = phone_number[1:]
    if len(phone_number) != 10:
        return False

    #area_code: XXXxxxxxxx 
    #head:      xxxXXXxxxx
    #tail:      xxxxxxXXXX
    area_code = phone_number[ :3]
    head      = phone_number[3:6]
    tail      = phone_number[6: ]

    if area_code in BAD_AREA_CODES:
        return False
    if head[0] == '1':
        return False
    if head[1:] == '11':
        return False

    #any other ideas?
    return True

This covers quite a bit. It's not a regex, but it does map to other languages pretty easily.

201赞 8 revs, 7 users 64%Tim Groeneveld #27

I would also suggest looking at the "libphonenumber" Google Library. I know it is not regex but it does exactly what you want.

For example, it will recognize that:

15555555555

是一个可能的数字,但不是有效的数字。它还支持美国以外的国家/地区。

功能亮点:

  • 解析/格式化/验证世界上所有国家/地区的电话号码。
  • getNumberType- 根据数字本身获取数字的类型;能够区分固定电话、移动电话、免费电话、保费、分摊费用、VoIP 和个人号码(只要可行)。
  • isNumberMatch- 获取两个数字是否相同的置信度。
  • getExampleNumber/getExampleNumberByType- 提供所有国家/地区的有效示例号码,并可选择指定所需的示例电话号码类型。
  • isPossibleNumber- 仅使用长度信息快速猜测号码是否为可能的电话号码,这比完全验证快得多。
  • isValidNumber- 使用长度和前缀信息对某个区域的电话号码进行全面验证。
  • AsYouTypeFormatter- 当用户输入每个数字时,即时设置电话号码的格式。
  • findNumbers- 在文本输入中查找数字。
  • PhoneNumberOfflineGeocoder- 提供与电话号码相关的地理信息。

例子

电话号码验证的最大问题是它非常依赖于文化。

  • 美洲
    • (408) 974–2042有效的美国号码
    • (999) 974–2042不是有效的美国号码
  • 澳大利亚
    • 0404 999 999有效的澳大利亚号码
    • (02) 9999 9999也是一个有效的澳大利亚号码
    • (09) 9999 9999不是有效的澳大利亚号码

正则表达式可用于检查电话号码的格式,但它实际上无法检查电话号码的有效性

我建议跳过一个简单的正则表达式来测试你的电话号码,并使用一个库,如谷歌的libphonenumber(链接到GitHub项目)。

介绍 libphonenumber!

使用一个更复杂的示例,您可以从 libphonenumber(链接到在线演示)中获取以下数据1-234-567-8901 x1234

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     true

Formatting Results:

E164 format                    +12345678901
Original format                (234) 567-8901 ext. 123
National format                (234) 567-8901 ext. 123
International format           +1 234-567-8901 ext. 123
Out-of-country format from US  1 (234) 567-8901 ext. 123
Out-of-country format from CH  00 1 234-567-8901 ext. 123

因此,您不仅可以了解电话号码是否有效(确实有效),还可以在区域设置中获得一致的电话号码格式。

作为奖励,也有许多数据集来检查电话号码的有效性,因此检查诸如((02)9999 9999的国际版本)之类的数字将返回为带有格式的有效数字:libphonenumber+61299999999

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     true

Formatting Results

E164 format                    +61299999999
Original format                61 2 9999 9999
National format                (02) 9999 9999
International format           +61 2 9999 9999
Out-of-country format from US  011 61 2 9999 9999
Out-of-country format from CH  00 61 2 9999 9999

libphonenumber 还为您提供了许多其他好处,例如获取检测到电话号码的位置,以及从电话号码中获取时区信息:

PhoneNumberOfflineGeocoder Results
Location        Australia

PhoneNumberToTimeZonesMapper Results
Time zone(s)    [Australia/Sydney]

但无效的澳大利亚电话号码 ((09) 9999 9999) 返回它不是有效的电话号码。

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     false

Google 的版本有 Java 和 Javascript 的代码,但人们也为使用 Google i18n 电话号码数据集的其他语言实现了库:

除非您确定您将始终接受来自一个区域设置的号码,并且它们始终采用一种格式,否则我强烈建议您不要为此编写自己的代码,并使用 libphonenumber 来验证和显示电话号码。

评论

0赞 michaelhanson 9/13/2016
注意到现在还有 Go 端口:github.com/ttacon/libphonenumber
0赞 BugHunterUK 11/29/2016
在检查它是否是可能的数字时,您不需要指定国家/地区代码吗?我正在使用 PHP 版本,如果我输入一个英国数字,例如(用实数替换 0),我会出错。但是,如果我指定国家/地区代码,它就会通过。07700000000Missing or invalid default region.
3赞 IMSoP 3/23/2018
@BugHunterUK(以及任何遇到这个问题并想知道同样问题的人)在解析数字时,您可以指定预期的区域,库将在该区域中查找非国际数字。如果您不指定,它将拒绝任何非有效国际格式的内容。
0赞 DeeZone 5/6/2019
考虑 github.com/nyaruka/phonenumbers 因为它已成为 Google 推荐的“官方”Go 包,而不是 libphonenumber。
0赞 dimplex 7/9/2020
我可以确认@BugHunterUK说的话。花了时间到达那里,但结果完全符合预期 - 以任何格式接受本地号码以及所有完全指定的国际格式。
91赞 8 revs, 5 users 74%Ismael Miguel #28

/^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d*)\)?)[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?)+)(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i

这匹配:

 - (+351) 282 43 50 50
 - 90191919908
 - 555-8909
 - 001 6867684
 - 001 6867684x1
 - 1 (234) 567-8901
 - 1-234-567-8901 x1234
 - 1-234-567-8901 ext1234
 - 1-234 567.89/01 ext.1234
 - 1(234)5678901x1234
 - (123)8575973
 - (0055)(123)8575973
 - +1 282 282 2828

在$n上,它可以保存:

  1. 国家指标
  2. 电话号码
  3. 外延

您可以在 https://regex101.com/r/kFzb1s/42 上对其进行测试

评论

0赞 bafromca 3/8/2014
这是我见过的最全面的正则表达式。在你删除之前,它很容易绕过,否则我可以使用或类似的东西绕过它。(对不起,删除了我的最后一条评论)^$[111] [111] [1111]111--111--1111
17赞 Matt Cashatt 7/19/2014
^^^这是一个很好的例子,说明为什么评论线程不应该去聊天。我对这次对话的结果非常感兴趣,并且需要知道这个 ReGex 是否足够坚固,可以在我的应用程序中使用。不幸的是,聊天对话现在已经消失了。
2赞 Ismael Miguel 7/20/2014
老实说,我没有去聊天。在多次询问解释后,我没有任何信息。您可以随时使用您在网上找到的各种数字以多种格式尝试。我尝试的一件事是使用多个电话号码,但如果它们周围有空格,效果就不那么好了。我必须找到一个解决方案来计算数字数量并强制执行特定数量。
2赞 Ismael Miguel 2/22/2022
@heisenberg 谢谢你指出来,我设法修复了它。此外,我还添加了一个与单元测试不同的链接,以确保它正常工作。这个错误是一个不应该存在的单曲。?
1赞 Ismael Miguel 3/13/2023
@Gavin我也对其进行了编辑以匹配。问题是我假设指示性是 1 或 9,然后是 1 个或多个数字,但美国使用 ,这打破了“1 个或多个数字”。它现在适用于这些人。+1+1
1赞 Sinan Eldem #29

土耳其的工作示例,只需更改

d{9}

根据您的需要并开始使用它。

function validateMobile($phone)
{
    $pattern = "/^(05)\d{9}$/";
    if (!preg_match($pattern, $phone))
    {
        return false;
    }
    return true;
}

$phone = "0532486061";

if(!validateMobile($phone))
{
    echo 'Incorrect Mobile Number!';
}

$phone = "05324860614";
if(validateMobile($phone))
{
    echo 'Correct Mobile Number!';
}
8赞 Drew Thomas #30

After reading through these answers, it looks like there wasn't a straightforward regular expression that can parse through a bunch of text and pull out phone numbers in any format (including international with and without the plus sign).

Here's what I used for a client project recently, where we had to convert all phone numbers in any format to tel: links.

So far, it's been working with everything they've thrown at it, but if errors come up, I'll update this answer.

Regex:

/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/

PHP function to replace all phone numbers with tel: links (in case anyone is curious):

function phoneToTel($number) {
    $return = preg_replace('/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/', '<a href="tel:$1$3$4$5">$1 ($3) $4-$5</a>', $number); // includes international
    return $return;
}

评论

0赞 Varda Elentári 10/14/2015
This regular expression matched .+1 1234562222222222222222222222
0赞 thexande 3/9/2017
why not just return?
0赞 Ben Wheeler 3/26/2020
False positive for "999999999999999999999999999999999999999"
57赞 7 revs, 3 users 95%vapcguy #31

I answered this question on another SO question before deciding to also include my answer as an answer on this thread, because no one was addressing how to require/not require items, just handing out regexs: Regex working wrong, matching unexpected things

From my post on that site, I've created a quick guide to assist anyone with making their own regex for their own desired phone number format, which I will caveat (like I did on the other site) that if you are too restrictive, you may not get the desired results, and there is no "one size fits all" solution to accepting all possible phone numbers in the world - only what you decide to accept as your format of choice. Use at your own risk.

Quick cheat sheet

  • Start the expression: /^
  • If you want to require a space, use: or [\s]\s
  • If you want to require parenthesis, use: and . Using and is ugly and can make things confusing.[(][)]\(\)
  • If you want anything to be optional, put a after it?
  • If you want a hyphen, just type or . If you do not put it first or last in a series of other characters, though, you may need to escape it: -[-]\-
  • If you want to accept different choices in a slot, put brackets around the options: will require a hyphen, period, or space. A question mark after the last bracket will make all of those optional for that slot.[-.\s]
  • \d{3} : Requires a 3-digit number: 000-999. Shorthand for .[0-9][0-9][0-9]
  • [2-9] : Requires a digit 2-9 for that slot.
  • (\+|1\s)? : Accept a "plus" or a 1 and a space (pipe character, , is "or"), and make it optional. The "plus" sign must be escaped.|
  • If you want specific numbers to match a slot, enter them: will require a 2, 4, or 6. or will require 77 or 78.[246](?:77|78)[77|78]
  • $/ : End the expression

评论

1赞 Ataboy Josef 1/7/2015
This is very useful, but I doubt and looking for a {min,max} expression. Can you help?
0赞 vapcguy 1/8/2015
If it is a single digit we're talking about (and you can make it match according to that), see the block I put there. That means your min is 2, and your max is 9. Adjust accordingly.[2-9]
19赞 2 revsStuart Kershaw #32

Here's a wonderful pattern that most closely matched the validation that I needed to achieve. I'm not the original author, but I think it's well worth sharing as I found this problem to be very complex and without a concise or widely useful answer.

The following regex will catch widely used number and character combinations in a variety of global phone number formats:

/^\s*(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/gm

Positive:
+42 555.123.4567
+1-(800)-123-4567
+7 555 1234567
+7(926)1234567
(926) 1234567
+79261234567
926 1234567
9261234567
1234567
123-4567
123-89-01
495 1234567
469 123 45 67
89261234567
8 (926) 1234567
926.123.4567
415-555-1234
650-555-2345
(416)555-3456
202 555 4567
4035555678
1 416 555 9292

Negative:
926 3 4
8 800 600-APPLE

Original source: http://www.regexr.com/38pvb

评论

0赞 Jon Schneider 6/24/2016
This has some limited support for extensions. It matches "616-555-1234 x567" but not "616-555-1234 ext. 567".
3赞 mikep 11/23/2017
False positive for e.g."-------((((((55555555" or "99999999999999999999999"
0赞 BIOHAZARD 12/9/2018
It does not validate Nitherland macdonalds number +31 76 596 4192 (I was just testing for random numbers)
-5赞 bcherny #33
/\b(\d{3}[^\d]{0,2}\d{3}[^\d]{0,2}\d{4})\b/
14赞 Herobrine2Nether #34

I found this to work quite well:

^\(*\+*[1-9]{0,3}\)*-*[1-9]{0,3}[-. /]*\(*[2-9]\d{2}\)*[-. /]*\d{3}[-. /]*\d{4} *e*x*t*\.* *\d{0,4}$

It works for these number formats:

1-234-567-8901
1-234-567-8901 x1234
1-234-567-8901 ext1234
1 (234) 567-8901
1.234.567.8901
1/234/567/8901
12345678901
1-234-567-8901 ext. 1234
(+351) 282 433 5050

Make sure to use global AND multiline flags to make sure.

Link: http://www.regexr.com/3bp4b

1赞 2 revsMortimer #35

It's near to impossible to handle all sorts of international phone numbers using simple regex.

You'd be better off using a service like numverify.com, they're offering a free JSON API for international phone number validation, plus you'll get some useful details on country, location, carrier and line type with every request.

2赞 Sai prateek #36

Find String regex = "^\\+(?:[0-9] ?){6,14}[0-9]$";

helpful for international numbers.

0赞 Gautam Sharma #37

Note It takes as an input a US mobile number in any format and optionally accepts a second parameter - set true if you want the output mobile number formatted to look pretty. If the number provided is not a mobile number, it simple returns false. If a mobile number IS detected, it returns the entire sanitized number instead of true.

    function isValidMobile(num,format) {
        if (!format) format=false
        var m1 = /^(\W|^)[(]{0,1}\d{3}[)]{0,1}[.]{0,1}[\s-]{0,1}\d{3}[\s-]{0,1}[\s.]{0,1}\d{4}(\W|$)/
        if(!m1.test(num)) {
           return false
        }
        num = num.replace(/ /g,'').replace(/\./g,'').replace(/-/g,'').replace(/\(/g,'').replace(/\)/g,'').replace(/\[/g,'').replace(/\]/g,'').replace(/\+/g,'').replace(/\~/g,'').replace(/\{/g,'').replace(/\*/g,'').replace(/\}/g,'')
        if ((num.length < 10) || (num.length > 11) || (num.substring(0,1)=='0') || (num.substring(1,1)=='0') || ((num.length==10)&&(num.substring(0,1)=='1'))||((num.length==11)&&(num.substring(0,1)!='1'))) return false;
        num = (num.length == 11) ? num : ('1' + num);   
        if ((num.length == 11) && (num.substring(0,1) == "1")) {
            if (format===true) {
               return '(' + num.substr(1,3) + ') ' + num.substr(4,3) + '-' + num.substr(7,4)
            } else {
               return num
            }
        } else {
            return false;
        }
    }
0赞 Shailendra Madda #38

Try this (It is for Indian mobile number validation):

if (!phoneNumber.matches("^[6-9]\\d{9}$")) {
  return false;
} else {
  return true;
}

评论

0赞 nice_dev 1/26/2019
Why not just return the output of ?matches
1赞 SIM #39

As there is no language tag with this post, I'm gonna give a solution used within python.regex

The expression itself:

1[\s./-]?\(?[\d]+\)?[\s./-]?[\d]+[-/.]?[\d]+\s?[\d]+

When used within python:

import re

phonelist ="1-234-567-8901,1-234-567-8901 1234,1-234-567-8901 1234,1 (234) 567-8901,1.234.567.8901,1/234/567/8901,12345678901"

phonenumber = '\n'.join([phone for phone in re.findall(r'1[\s./-]?\(?[\d]+\)?[\s./-]?[\d]+[-/.]?[\d]+\s?[\d]+' ,phonelist)])
print(phonenumber)

Output:

1-234-567-8901
1-234-567-8901 1234
1-234-567-8901 1234
1 (234) 567-8901
1.234.567.8901
1/234/567/8901
12345678901
-1赞 3 revsoriadam #40

since there are so many options to write a phone number, one can just test that are enough digits in it, no matter how they are separated. i found 9 to 14 digits work for me:

^\D*(\d\D*){9,14}$

true:

  • 123456789
  • 1234567890123
  • +123 (456) 78.90-98.76

false:

  • 123
  • (1234) 1234
  • 9007199254740991
  • 123 wont do what you tell me
  • +123 (456) 78.90-98.76 #543 ext 210>2>5>3
  • (123) 456-7890 in the morning (987) 54-3210 after 18:00 and ask for Shirley

if you do want to support those last two examples - just remove the upper limit:

(\d\D*){9,}

(the are not needed if there's no upper limit)^$

0赞 3 revsDigitShifter #41

Java generates REGEX for valid phone numbers

Another alternative is to let Java generate a REGEX that macthes all variations of phone numbers read from a list. This means that the list called validPhoneNumbersFormat, seen below in code context, is deciding which phone number format is valid.

Note: This type of algorithm would work for any language handling regular expressions.

Code snippet that generates the REGEX:

Set<String> regexSet = uniqueValidPhoneNumbersFormats.stream()
        .map(s -> s.replaceAll("\\+", "\\\\+"))
        .map(s -> s.replaceAll("\\d", "\\\\d"))
        .map(s -> s.replaceAll("\\.", "\\\\."))
        .map(s -> s.replaceAll("([\\(\\)])", "\\\\$1"))
        .collect(Collectors.toSet());

String regex = String.join("|", regexSet);

Code snippet in context:

public class TestBench {

    public static void main(String[] args) {
        List<String> validPhoneNumbersFormat = Arrays.asList(
                "1-234-567-8901",
                "1-234-567-8901 x1234",
                "1-234-567-8901 ext1234",
                "1 (234) 567-8901",
                "1.234.567.8901",
                "1/234/567/8901",
                "12345678901",
                "+12345678901",
                "(234) 567-8901 ext. 123",
                "+1 234-567-8901 ext. 123",
                "1 (234) 567-8901 ext. 123",
                "00 1 234-567-8901 ext. 123",
                "+210-998-234-01234",
                "210-998-234-01234",
                "+21099823401234",
                "+210-(998)-(234)-(01234)",
                "(+351) 282 43 50 50",
                "90191919908",
                "555-8909",
                "001 6867684",
                "001 6867684x1",
                "1 (234) 567-8901",
                "1-234-567-8901 x1234",
                "1-234-567-8901 ext1234",
                "1-234 567.89/01 ext.1234",
                "1(234)5678901x1234",
                "(123)8575973",
                "(0055)(123)8575973"
        );

        Set<String> uniqueValidPhoneNumbersFormats = new LinkedHashSet<>(validPhoneNumbersFormat);

        List<String> invalidPhoneNumbers = Arrays.asList(
                "+210-99A-234-01234",       // FAIL
                "+210-999-234-0\"\"234",    // FAIL
                "+210-999-234-02;4",        // FAIL
                "-210+998-234-01234",       // FAIL
                "+210-998)-(234-(01234"     // FAIL
        );
        List<String> invalidAndValidPhoneNumbers = new ArrayList<>();
        invalidAndValidPhoneNumbers.addAll(invalidPhoneNumbers);
        invalidAndValidPhoneNumbers.addAll(uniqueValidPhoneNumbersFormats);

        Set<String> regexSet = uniqueValidPhoneNumbersFormats.stream()
                .map(s -> s.replaceAll("\\+", "\\\\+"))
                .map(s -> s.replaceAll("\\d", "\\\\d"))
                .map(s -> s.replaceAll("\\.", "\\\\."))
                .map(s -> s.replaceAll("([\\(\\)])", "\\\\$1"))
                .collect(Collectors.toSet());

        String regex = String.join("|", regexSet);

        List<String> result = new ArrayList<>();
        Pattern pattern = Pattern.compile(regex);
        for (String phoneNumber : invalidAndValidPhoneNumbers) {
            Matcher matcher = pattern.matcher(phoneNumber);
            if(matcher.matches()) {
                result.add(matcher.group());
            }
        }

        // Output:
        if(uniqueValidPhoneNumbersFormats.size() == result.size()) {
            System.out.println("All valid numbers was matched!\n");
        }    
        result.forEach(System.out::println); 
    }

}

Output:

All valid numbers was matched!

1-234-567-8901
1-234-567-8901 x1234
1-234-567-8901 ext1234
...
...
...
0赞 victoria55 #42

Although it's not regex, you can use the function validate_phone() from the Python library DataPrep to validate US phone numbers. Install it with .pip install dataprep

>>> from dataprep.clean import validate_phone
>>> df = pd.DataFrame({'phone': ['1-234-567-8901', '1-234-567-8901 x1234', 
         '1-234-567-8901 ext1234', '1 (234) 567-8901', '1.234.567.8901',
         '1/234/567/8901', 12345678901, '12345678', '123-456-78987']})
>>> validate_phone(df['phone'])
0     True
1     True
2     True
3     True
4     True
5     True
6     True
7    False
8    False
Name: phone, dtype: bool
-2赞 Tabraiz Malik #43

Simple regex and other tricks works.

.*

but showing an Hint / Example / Placeholder / Tooltip for the input.

Then verifying on the frontend before submitting that the format is actually correct is a best experience out there.

This would simplify formats for an inexperienced user.

0赞 Sanka Sanjeewa #44

I chose below regExp but when I copy and paste phone numbers it didn't work

/^(\+?\d{0,4})?[ -]?(\(?\d{3}\)?)[ -]?(\(?\d{3}\)?)[ -]?(\(?\d{4}\)?)?$/

The reason is there was a different dash symbol(this not ). So I modified regExp again by adding it too.-

/^(\+?\d{0,4})?[ -‑]?(\(?\d{3}\)?)[ -‑]?(\(?\d{3}\)?)[ -‑]?(\(?\d{4}\)?)?$/
0赞 2 revsRatul Hasan #45

I believe this is the one You'll need to detect phone numbers, you also should use a line of programming just to ensure a valid number.

((\+ ?)?(\(\d{1,5}\)[ \-.]?)?\d+([ \-.]?\d+)*)

The 1st capturing group is the number.

This will check

  • + country code
  • (555)
  • multiple (- and space)

Once you get the number, to verify it's best to check their length (min 4 yes 4 digits exist, max 15) Python example:

def validate_number(number:str):
    n = sum([1 if c.isdigit()  else 0 for c in number ])
    
    return n >= 4 and n <= 15

JS example

function validate_number(number){
    n = 0
    for(i=0;i<number.length;i++){
        // check if the character is a number
        if(/^\d+$/.test(number.charAt(i))){
            n += 1
        }
    }
    return (n>=4 && n<=15)
}