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

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

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


当前回答

你看过RegExLib了吗?

输入一个美国的电话号码,你会发现很多可能性。

其他回答

我不建议使用正则表达式。

和上面的答案一样,去掉所有难看的电话号码,这样你就只剩下一串数字字符,如果提供扩展名的话,还会有一个'x'。

在Python中:

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

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

这涵盖了相当多的内容。它不是一个正则表达式,但它确实很容易映射到其他语言。

我还建议查看“libphonenumber”谷歌库。我知道它不是正则表达式,但它确实是你想要的。

例如,它会识别:

15555555555

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

功能亮点:

Parsing/formatting/validating phone numbers for all countries/regions of the world. getNumberType - gets the type of the number based on the number itself; able to distinguish Fixed-line, Mobile, Toll-free, Premium Rate, Shared Cost, VoIP and Personal Numbers (whenever feasible). isNumberMatch - gets a confidence level on whether two numbers could be the same. getExampleNumber/getExampleNumberByType - provides valid example numbers for all countries/regions, with the option of specifying which type of example phone number is needed. isPossibleNumber - quickly guessing whether a number is a possible phonenumber by using only the length information, much faster than a full validation. isValidNumber - full validation of a phone number for a region using length and prefix information. AsYouTypeFormatter - formats phone numbers on-the-fly when users enter each digit. findNumbers - finds numbers in text input. PhoneNumberOfflineGeocoder - provides geographical information related to a phone number.

例子

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

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

正则表达式可以用于检查电话号码的格式,但它不能真正地检查电话号码的有效性。

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

引入libphonenumber !

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

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)99999999的国际版本)这样的号码,返回一个带有格式的有效号码:

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)99999999)返回它不是一个有效的电话号码。

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/daviddrysdale/python-phonenumbers Ruby: https://github.com/sstephenson/global_phone c#: https://github.com/twcclegg/libphonenumber-csharp objective - c: https://github.com/iziz/libPhoneNumber-iOS JavaScript: https://github.com/ruimarinho/google-libphonenumber 灵丹妙药:https://github.com/socialpaymentsbv/ex_phone_number

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

Find String regex = "^\\+(?:[0 - 9] ?){6、14}[0 - 9]美元”;

对国际号码很有用。

事实上,至少在北美,有一个叫做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+))?$

我发现这个方法非常有效:

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

它适用于以下数字格式:

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