用于电话号码验证的全面正则表达式

A comprehensive regex for phone number validation

我正在尝试建立一个综合的regex来验证电话号码。理想情况下,它可以处理国际格式,但它必须处理美国格式,包括:

  • 1-23 4-567—8901
  • 1-234-567-8901 x1234
  • 1-234-567-8901分机1234
  • 1(234)567-8901
  • 1.23 4.567.8901
  • 1/234/567/8901
  • 一百二十三亿四千五百六十七万八千九百零一

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


更好的选择…只需去掉输入端的所有非数字字符(除"x"和前导"+"符号外),注意英国人在要求使用国际前缀时(在这种特定情况下,您应该完全放弃(0))会倾向于用非标准格式+44 (0) ...书写数字。

然后,你会得到如下的值:

1
2
3
4
5
6
7
8
9
 12345678901
 12345678901x1234
 345678901x1234
 12344678901
 12345678901
 12345678901
 12345678901
 +4112345678
 +441234567890

然后当你显示时,重新格式化到你的心形内容。例如

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


事实证明,至少在北美,有一种特殊的东西叫做"保姆"。

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

这里是一个7或10位数字的regex,允许扩展,分隔符是空格、短划线或句点:

1
^(?:(?:\+?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+))?$


1
.*

如果用户想给你他的电话号码,那就相信他能把它弄好。如果他不想给你,那么强迫他输入一个有效的数字,要么把他送到竞争对手的网站,要么让他输入一个符合你的regex的随机字符串。我甚至可能会想查找一个高利率性热线的号码,然后输入这个号码。

我也会将以下任何一项视为网站上的有效条目:

1
2
3
"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"


我还建议您查看"libphonenumber"谷歌库。我知道它不是雷杰克斯,但它完全符合你的要求。

例如,它将认识到:

1
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不是有效的澳大利亚号码

正则表达式可以用来检查电话号码的格式,但实际上它不能检查电话号码的有效性。

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

介绍libphonenumber!

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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

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

另外,libphonenumber有许多数据集用于检查电话号码的有效性,因此,检查诸如+61299999999之类的号码((02) 9999 9999的国际版本)将返回一个带格式的有效号码:

1
2
3
4
5
6
7
8
9
10
11
12
13
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还为您提供了许多额外的好处,例如获取检测到电话号码的位置,以及从电话号码获取时区信息:

1
2
3
4
5
PhoneNumberOfflineGeocoder Results
Location        Australia

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

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

1
2
3
4
Validation Results

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

谷歌的版本有Java和JavaScript的代码,但是人们也为使用谷歌I18N电话号码数据集的其他语言实现了库:

  • php:https://github.com/giggsey/libphonenumber-for-php
  • python:https://github.com/davidrysdale/python-phonenumbers
  • 鲁比:https://github.com/sstephenson/global_phone
  • C:https://github.com/twccleg/libphonenumber-csharp
  • 目标C:https://github.com/iziz/libphonenumber-ios
  • javascript:https://github.com/ruimarinho/google-libphonenumber
  • elixir:https://github.com/socialpaymentsbv/ex_电话号码

除非你确定你总是接受一个地区的电话号码,而且他们总是采用一种格式,否则我强烈建议不要为此编写自己的代码,并使用libphonenumber验证和显示电话号码。


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

这场比赛:

1
2
3
4
5
6
7
8
9
10
11
12
 - (+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

在$n上,它可以节省:

  • 国家标志
  • 电话号码
  • 延伸
  • 您可以在https://www.regexpal.com/上测试它?FAM=99127


    虽然去除所有空白的答案是整洁的,但它并不能真正解决所提出的问题,即找到一个regex。以我的测试脚本为例,该脚本下载网页并使用regex提取所有电话号码。既然你无论如何都需要一个regex,你最好让regex来做所有的工作。我想到了这个:

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

    下面是一个测试它的Perl脚本。匹配时,$1包含区号,$2和$3包含电话号码,$5包含分机号。我的测试脚本从Internet下载一个文件并打印其中的所有电话号码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #!/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]
    " if not defined $4;
                    print"match [$1-$2-$3 $5]
    " if defined $4;
            }
            else
            {
                    print"no match [$num]
    ";
            }
    }

    #
    # 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
    ";
            }
    }

    编辑:

    您可以将w*更改为s*w吗? s*在regex中拧紧一点。我在编写表单时并没有考虑使用regex来验证用户在表单上的输入,但这种更改使使用regex成为可能。

    1
    '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*))?';


    在决定将我的答案也包括在这个线程的答案中之前,我在另一个so问题上回答了这个问题,因为没有人在解决如何要求/不要求项目,只是分发regex:regex工作错误,匹配意外事件

    从我在那个网站上的帖子中,我创建了一个快速指南来帮助任何人为他们自己想要的电话号码格式制作自己的regex,我会警告(就像我在另一个网站上做的那样),如果你限制太多,你可能得不到想要的结果,并且没有"一刀切"的解决方案来接受所有可能的电话号码。世界上-只有你决定接受的作为你选择的格式。自担风险使用。

    快速备忘单

    • 开始表达式:/^
    • 如果需要空间,请使用:[\s]\s
    • 如果需要括号,请使用:[(][)]。使用\(\)是丑陋的,会使事情变得混乱。
    • 如果你想选择什么,在它后面放一个?
    • 如果需要连字符,只需键入-[-]。但是,如果您不将它放在一系列其他字符中的第一个或最后一个字符中,则可能需要对其进行转义:\-
    • 如果您想在一个插槽中接受不同的选择,请在选项周围加上括号:[-.\s]将需要连字符、句点或空格。最后一个括号后面的问号将使该插槽的所有这些选项都是可选的。
    • \d{3}:需要一个3位数:000-999。速记[0-9][0-9][0-9]
    • [2-9]:该插槽需要一个数字2-9。
    • (\+|1\s)?:接受一个"加号"或一个1和一个空格(管道字符,|是"或"),并使其可选。"加号"必须转义。
    • 如果您希望特定号码与插槽匹配,请输入它们:[246]需要2、4或6。[77|78]需要77或78。
    • $/结束表达式


    我写得最简单(尽管我不需要点)。

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

    如下文所述,它只检查字符,而不检查其结构/顺序。


    请注意,删除()字符不适用于常见的英国号码书写方式:+44 (0) 1234 567890表示拨国际号码:+441234567890或者在英国拨01234567890


    如果您只想验证字段中没有随机垃圾(例如,来自表单垃圾邮件发送者),那么这个regex应该做得很好:

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

    注意,它没有任何特殊的规则来确定这些数字中有多少个数字或哪些数字是有效的,它只是验证只有数字、括号、短划线、加号、空格、磅、星号、句点、逗号或字母ext存在。

    它应该与国际号码和本地化格式兼容。对于某些区域,您是否预见到需要使用方括号、花括号或尖括号?(目前不包括在内)。

    如果你想保持每个数字的规则(比如美国的区号和前缀(交换码)必须在200-999之间),那么祝你好运。维持一个复杂的规则集,这个规则集在未来任何时候都可能被世界上任何一个国家过时,这听起来并不有趣。

    虽然在服务器端剥离所有/大多数非数字字符可能会很好地工作(特别是如果您计划将这些值传递给拨号程序),但您可能不希望在验证期间破坏用户的输入,特别是如果您希望他们在另一个字段中进行更正。


    你看过Regexlib吗?

    输入我们的电话号码带来了很多可能性。


    我觉得这个很管用:

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

    它适用于以下数字格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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

    确保使用全局和多行标志来确保。

    链接:http://www.regexr.com/3bp4b


    我尝试一个无限制的正则表达式:

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

    接受:

    1
    2
    3
    4
    5
    6
    +(01) 123 (456) 789 ext555
    123456
    *44 123-456-789 [321]
    123456
    123456789012345678901234567890123456789012345
    *****++[](][((( 123456tteexxttppww

    拒绝:

    1
    2
    3
    4
    5
    6
    mob 07777 777777
    1234 567 890 after 5pm
    john smith
    (empty)
    1234567890123456789012345678901234567890123456
    911

    您可以对其进行消毒以供显示。在验证之后,它可能是一个数字。


    如果您谈论的是表单验证,那么验证正确含义和正确数据的regexp将非常复杂,因为不同的国家和提供商标准不同。也很难跟上时代。

    我将这个问题解释为寻找一个广泛有效的模式,这种模式在内部可能不一致——例如拥有一组有效的数字,但没有验证主干线、交换等是否符合国家代码前缀的有效模式。

    北美是直截了当的,在国际上,我更喜欢使用"惯用"模式,它涵盖了人们指定和记住数字的方式:

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

    北美模式确保如果包含一个圆括号,两个圆括号都是。国际帐户有一个可选的首字母"+"和国家代码。在那之后,你就习惯了。有效匹配将是:

    • (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

    这可能有偏见,因为我的经验仅限于北美、欧洲和亚洲的一小部分地区。


    我的直觉被对这个话题的大量回复所强化——这个问题的解决方案实际上是无限多的,没有一个会是优雅的。

    老实说,我建议你不要尝试验证电话号码。即使你能写一个大的,毛茸茸的验证器,允许所有不同的合法格式,它最终会允许几乎任何东西,甚至在一开始就很像一个电话号码。

    在我看来,最优雅的解决方案是验证最小长度,而不是更多。


    这是菲律宾手机号码的简单正则表达式模式:

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

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

    将匹配这些:

    1
    2
    3
    4
    5
    +63.917.123.4567  
    +63-917-123-4567  
    +63 917 123 4567  
    +639171234567  
    09171234567

    第一个将匹配任何两位数的国家代码,而第二个将只匹配菲律宾国家代码。

    在此测试:http://refidle.com/1ox


    这里有一个非常好的模式,它最符合我需要实现的验证。我不是最初的作者,但我认为这是值得分享的,因为我发现这个问题非常复杂,没有一个简明或广泛有用的答案。

    以下regex将捕获各种全球电话号码格式中广泛使用的号码和字符组合:

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

    阳性:
    +42 555.123.4567
    +1-(800)-123-4567
    +7 555 1234567
    +7(926)1234567
    (926)1234567
    +79261234567
    926 1234567
    9261234567<BR/>1234567<BR/>123-467123-8901
    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<BR/>1 416 555 555

    否定的:
    926 3 4<BR/>8 800 600苹果

    原始资料来源:http://www.regexr.com/38pvb


    你很难用一个简单的regex来处理国际号码,请看这篇关于国际(甚至北美)电话号码困难的文章。

    您需要解析前几个数字来确定国家代码是什么,然后根据国家采取不同的行动。

    除此之外-您提供的列表不包括另一种常见的美国格式-去掉了最初的1。在美国,大多数手机都不需要它,而且它会开始困扰年轻一代,除非他们已经打过国际长途。

    你已经确定这是个棘手的问题…

    -亚当


    在读完这些答案后,似乎没有一个简单的正则表达式可以通过一堆文本进行解析,并以任何格式提取电话号码(包括带有或不带加号的国际电话号码)。

    这是我最近在一个客户项目中使用的方法,我们必须将所有格式的电话号码转换为tel:links。

    到目前为止,它已经处理了所有他们抛出的东西,但是如果出现错误,我会更新这个答案。

    Regex:

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

    php函数将所有电话号码替换为tel:links(如果有人好奇):

    1
    2
    3
    4
    function phoneToTel($number) {
        $return = preg_replace('/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/', '$1 ($3) $4-$5', $number); // includes international
        return $return;
    }


    这是我迄今为止最好的尝试。它处理上面的格式,但我确信我遗漏了一些其他可能的格式。

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

    我相信数字::phone::us和regexp::common(尤其是regexp::common::uri::rfc2806的源代码)Perl模块会有所帮助。

    应该更详细地说明这个问题,以解释验证数字的目的。例如,911在美国是一个有效的号码,但911X不代表X的任何值。这样电话公司就可以在您拨号后进行计算。这个问题有几个不同之处。但是您的regex不检查区号部分,所以这似乎不是一个问题。

    就像验证电子邮件地址一样,即使你有一个有效的结果,在你尝试之前你也不知道它是否被分配给了某人。

    如果您试图验证用户输入,为什么不规范化结果并完成它呢?如果用户输入了一个您无法识别为有效数字的数字,请将其保存为输入的或去掉不可使用的字符。编号::phone::normalize perl模块可能是灵感的来源。


    我在一家市场调查公司工作,我们必须一直过滤这些类型的输入。你太复杂了。只需去掉非字母数字字符,看看是否有扩展名。

    为了进一步分析,您可以订阅许多提供商中的一个,这些提供商将为您提供访问有效数字数据库的权限,并告诉您它们是固定电话还是移动电话、断开连接等。这需要花费资金。


    对格式化字符进行替换,然后检查其余字符的电话有效性。在PHP中,

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

    打破这样复杂的regexp同样有效,但更简单。


    我在同一个问题上苦苦挣扎,试图证明我的应用程序的未来,但这些人让我走上了正确的方向。我并不是在检查数字本身,看它是否有效,我只是想确保输入的一系列数字可能有扩展名,也可能没有扩展名。

    最坏的情况是,如果用户必须从XML文件中提取一个未格式化的号码,他们仍然只需将这些号码输入手机的数字键盘012345678x5,没有真正的理由保持漂亮。这种正则表达式对我来说是这样的:

    1
    \d+ ?\w{0,9} ?\d+
    • 01234467 extension 123456
    • 01234567x123456
    • 01234567890


    我觉得这很有趣。我还没有测试过,但看起来好像可以用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    <?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.';
    }
    ?>


    您最好使用屏蔽输入。这样,用户只能输入数字,您可以根据自己的需要设置格式。我不确定这是否适用于Web应用程序,但是如果是,有一个非常点击jquery插件提供了一些选项。

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

    他们甚至在教程中讨论了如何屏蔽电话号码输入。


    这里有一个在JavaScript中很好地工作。它在一个字符串中,因为这正是Dojo小部件所期望的。

    它匹配一个10位数的北美NANP号码和可选扩展名。空格、短划线和句点是可接受的分隔符。

    1
    "^(\\(?\\d\\d\\d\\)?)( |-|\\.)?\\d\\d\\d( |-|\\.)?\\d{4,4}(( |-|\\.)?[ext\\.]+ ?\\d+)?$"

    1
    2
        pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$"
        validateat="onsubmit"

    必须以数字结尾,可以以(或+或数字)开头,并且可以包含+-(或)


    我的倾向是同意剥去非数字,只接受最好的东西。也许是为了确保至少有几个数字存在,尽管这确实禁止像字母电话号码"ask-jake"这样的事情发生。

    几个简单的Perl表达式可能是:

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

    使用第一个数字组来保持数字组在一起,这可能会提供格式化的线索。用第二个数字把所有的非数字都轻轻地扔了。

    是否担心可能需要暂停,然后输入更多的键?或者像555-1212(等待哔哔声)123?


    对于任何想用爱尔兰手机号码做类似事情的人,以下是一个简单的方法:

    http://iloviniii.com/?P=87

    PHP

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

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

    该链接上还有一个jquery解决方案。

    编辑:

    jquery解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
        $(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();
    });


    });

    来源。


    由于本文没有语言标签,我将给出一个在Python中使用的regex解决方案。

    表达式本身:

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

    在python中使用时:

    1
    2
    3
    4
    5
    6
    7
    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 = '
    '.join([phone for phone in re.findall(r'1[\s./-]?\(?[\d]+\)?[\s./-]?[\d]+[-/.]?[\d]+\s?[\d]+' ,phonelist)])
    print(phonenumber)

    输出:

    1
    2
    3
    4
    5
    6
    7
    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

    我不建议用正则表达式。

    和最上面的答案一样,去掉电话号码中所有的丑陋之处,这样,如果提供了扩展名,您就只剩下一串数字字符和一个'x'

    在Python中:

    注:BAD_AREA_CODES来自一个文本文件,您可以从网上获取。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    BAD_AREA_CODES = open('badareacodes.txt', 'r').read().split('
    ')

    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

    这涵盖了不少。它不是regex,但它很容易映射到其他语言。


    以土耳其为例,只需更改

    1
    d{9}

    根据你的需要,开始使用它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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!';
    }

    是否可以让for-display 4个单独的字段(区号、3位前缀、4位部分、扩展名)以便它们分别输入地址的每个部分,并且您可以分别验证每个部分?这样,您不仅可以使验证更加容易,还可以在数据库中以更一致的格式存储电话号码。


    使用简单的regex处理各种国际电话号码几乎是不可能的。

    你最好使用一个像numverify.com这样的服务,他们提供了一个免费的JSON API来进行国际电话号码验证,此外,你还可以在每个请求中获得一些关于国家、地点、运营商和线路类型的有用细节。


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

    有助于国际号码。


    请注意,它以任何格式输入一个美国移动电话号码,如果您希望输出的移动电话号码的格式看起来漂亮,可以选择接受第二个参数设置为真。如果提供的号码不是移动电话号码,它简单地返回false。如果检测到移动电话号码,它将返回整个已消毒的号码,而不是真的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        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;
            }
        }

    尝试此操作(用于印度手机号码验证):

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


    1
    /\b(\d{3}[^\d]{0,2}\d{3}[^\d]{0,2}\d{4})\b/