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

1054

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

  • 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
此答案已添加到Stack Overflow正则表达式FAQ,位于“常见验证任务”下。 - aliteralmind
不幸的是,访问那个页面并搜索“常见验证任务”没有任何结果… - Lewis Cianci
这是一个正则表达式任务吗? - Guildenstern
在某些情况下,这是一个 XY 问题。你要求一个谓词,如果电话号码有效则返回 True,但你真正想要的只是一个正确的电话号码。对于任何试图清理网页或手机应用程序中最终用户输入的电话号码的人,我建议只需编写4或5行代码,逐个字符从左到右进行处理并且删除所有非数字字符。(303)873-9919 变成了 3038739919。删除所有非数字字符后,您可以在正确的位置插入(点 .),插入(连字符 -)或斜杠。 - Samuel Muldoon
45个回答

6
我相信Number::Phone::USRegexp::Common(尤其是Regexp::Common::URI::RFC2806的源代码)Perl模块可以帮助解决问题。
问题可能需要更详细地说明验证号码的目的。例如,在美国,911是有效的号码,但对于任何x值,911x都不是有效的号码。这是为了让电话公司能够计算您拨打电话的时间。这个问题有几个变化。但是你的正则表达式没有检查区号部分,所以那似乎不是一个问题。
就像验证电子邮件地址一样,即使您得到了一个有效的结果,您也无法知道它是否被分配给某个人,直到您尝试使用它。
如果您正在尝试验证用户输入,为什么不规范化结果并完成呢?如果用户输入一个您无法识别为有效数字的数字,则可以将其保存为已输入或删除不可用字符。 Number::Phone::Normalize Perl模块可能是一种启发。

我要冒昧地说,在几乎所有应用程序中,允许911作为电话号码可能都是一个坏主意,这个正则表达式的设计需要注意。不过还是很不错的发现。 - Blank

5

在处理电话号码时,需要先对格式字符进行替换,然后检查剩余部分是否符合电话号码的规范。在PHP中,可以使用相应函数实现。

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

分解类似这样复杂的正则表达式同样有效,但更加简单易懂。

4
我在一家市场调研公司工作,我们经常需要过滤这些类型的输入。你把它弄得太复杂了。只需去除非字母数字字符,然后查看是否有扩展名即可。
如果需要进一步分析,您可以订阅其中一家提供者的服务,他们将为您提供有效号码数据库的访问权限,并告诉您它们是固定电话还是移动电话、已停机等信息。这需要花费一定的费用。

验证?123%$)*%()$ *()#456 () $#(#$ @ 8908将匹配您提出的解决方案。 - PlexQ
1
@PlexQ 555-123-1234,07777777777,90210,01/01/1901 - 用户在通过验证时会创造性地塞入垃圾数据。最好不要使用过于严格的验证方式并告诉他们错误,以免惹恼那些确实有一些奇怪数据的用户。 - ReactiveRaven

3
我曾经也遇到过同样的问题,试图让我的应用程序具备未来的可扩展性,但这些人帮我指明了正确的方向。实际上,我并没有检查数字本身是否有效,而是只是尝试确保输入了一系列可能具有扩展名的数字。
最坏的情况是用户必须从XML文件中提取一个未格式化的号码,他们仍然只需在电话号码键盘上键入数字012345678x5,没有任何理由使它变得漂亮。对于我来说,这种类型的正则表达式可能会像这样:
\d+ ?\w{0,9} ?\d+
  • 01234467 分机号 123456
  • 01234567x123456
  • 01234567890

3
您最好使用掩码输入来实现此功能。这样,用户只能输入数字,您可以自由格式化。如果这是一个Web应用程序,有一个非常方便的jQuery插件可以提供一些选项来完成此操作。 http://digitalbush.com/projects/masked-input-plugin/ 他们甚至在他们的教程中介绍了如何掩码电话号码输入。

3
我发现这是一件有趣的事情。虽然我没有测试过,但它看起来似乎能够工作。
<?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
http://www.bitrepository.com/how-to-validate-a-telephone-number.html 看起来是来源。 - James Paterson

3

以下代码可在JavaScript中正常运行,因为Dojo插件预期使用字符串。

该代码匹配10位的北美NANP号码,并接受可选的扩展名。空格、短横线和句点均可作为分隔符。

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

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

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


2

如果有人对使用爱尔兰手机号码进行类似操作感兴趣,以下是一种简单的实现方式:

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

在那个链接中,还有一个jQuery解决方案。
编辑:
jQuery解决方案:
    $(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.


2

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

有助于处理国际号码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接