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

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

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


当前回答

我也在为同样的问题而挣扎,试图让我的应用程序经得起未来的考验,但这些人让我走上了正确的方向。我实际上并不是在检查数字本身,看它是否有效,我只是试图确保输入的一系列数字可能有或没有扩展名。

最坏的情况是,如果用户必须从XML文件中提取一个未格式化的数字,他们仍然只是将数字输入到手机的数字pad 012345678x5中,没有真正的理由保持它的美观。这种RegEx对我来说是这样的:

\d+ ?\w{0,9} ?\d+

01234467分机号123456 01234567 x123456 01234567890

其他回答

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

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

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

.*

如果用户想要给你他们的电话号码,那么相信他们会把它做好。如果他们不想给你,那么强迫他们输入一个有效的数字,要么把他们送到竞争对手的网站,要么让他们输入一个符合你的正则表达式的随机字符串。我甚至可能会忍不住去查询占星热线的电话号码,然后输入这个号码。

我也会考虑以下任何一个网站上的有效条目:

"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"

我写得最简单(虽然我不需要点)。

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

正如下面提到的,它只检查字符,而不检查其结构/顺序

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

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

打破像这样复杂的regexp同样有效,但要简单得多。

如果可能的话,我建议有四个单独的字段——区域代码、3位前缀、4位部分、扩展名——这样用户就可以分别输入地址的每个部分,并且您可以分别验证每个部分。这样不仅可以简化验证,还可以将电话号码以更一致的格式存储在数据库中。