如何使用regex验证电话号码

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

  • 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

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

1159860 次浏览

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

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

你看过0号了吗?

输入美国电话号码带回了相当多的可能性。

事实证明,至少对北美来说,这是有一个规范的,叫做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+))?$

更好的选择……只是删除输入上的所有非数字字符(除了“x”和前导“+”符号),因为当被要求使用国际前缀时,英国倾向于以非标准形式+44 (0) ...写入数字(在这种情况下,您应该完全丢弃(0))。

然后,你最终会得到这样的值:

 1234567890112345678901x1234345678901x123412344678901123456789011234567890112345678901+4112345678+441234567890

然后当你显示时,重新格式化你心中的内容。

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

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

对于进一步的分析,您可以订阅许多提供商之一,该提供商将让您访问有效号码的数据库,并告诉您它们是固定电话还是手机,断开连接等。

如果可能的话,我建议有四个单独的字段-区号,3位前缀,4位部分,分机-以便用户可以单独输入地址的每个部分,您可以单独验证每个部分。这样,您不仅可以使验证更容易,还可以将电话号码以更一致的格式存储在数据库中。

你将很难用一个单一/简单的正则表达式处理国际号码,请参阅这篇文章关于国际(甚至北美)电话号码的困难。

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

除此之外-你给出的列表不包括另一种常见的美国格式-省略了最初的1。美国的大多数手机不需要它,除非他们拨打国际电话,否则它会开始困扰年轻一代。

你已经正确地认识到这是一个棘手的问题…

亚当

我相信::Phone::美国Regexp::Common(特别是Regexp::Common::URI::RFC2806的源代码)Perl模块可以提供帮助。

这个问题可能应该更详细地说明,以解释验证数字的目的。例如,911在美国是一个有效的号码,但911x不代表x的任何值。这样电话公司就可以计算出你何时完成拨号。这个问题有几种变体。但是你的正则表达式不会检查区号部分,所以这似乎并不是一个问题。

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

如果您正在尝试验证用户输入,为什么不将结果规范化并完成它呢?如果用户输入了一个您无法识别为有效数字的数字,请将其保存为输入或删除不可更改的字符。::Phone::归一化 Perl模块可能是灵感的来源。

尽管去掉所有空格的答案很简洁,但它并没有真正解决所提出的问题,即找到一个正则表达式。以我的测试脚本为例,该脚本下载一个网页并使用正则表达式提取所有电话号码。既然你无论如何都需要一个正则表达式,你不妨让正则表达式做所有的工作。我想出了这个:

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美元包含扩展名。我的测试脚本从互联网上下载一个文件并打印其中的所有电话号码。

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

编辑:

您可以将正则表达式中的\W*更改为\s*\W?\s*以稍微收紧它。当我编写正则表达式时,我并没有考虑在表单上验证用户输入,但这种更改使得可以为此目的使用正则表达式。

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

我倾向于同意剥离非数字并接受其中的内容是最好的。也许是为了确保至少有几个数字存在,尽管这确实禁止诸如字母电话号码“ASK-JAKE”之类的东西。

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

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

使用第一个将数字组保持在一起,这可能会提供格式化线索。使用第二个简单地抛出所有非数字。

是担心可能需要暂停,然后输入更多的键?还是像555-1212(等待哔声)123这样的东西?

如果您谈论的是表单验证,由于不同的国家和提供者标准,验证正确含义和正确数据的正则表达式将非常复杂。也很难跟上时代。

我把这个问题解释为寻找一个广泛有效的模式,它可能不是内部一致的——例如,有一组有效的数字,但没有验证中继线、交换机等对国家代码前缀的有效模式。

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

^((((\(\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

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

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

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

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

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

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

像这样打破一个复杂的regexp可能同样有效,但更简单。

.*

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

我还会考虑以下任何一项作为网站上的有效条目:

"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\(\)\/\+ \-]*)$

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

请注意,剥离()字符不适用于常见的英国数字书写风格:+44 (0) 1234 567890这意味着拨打国际号码:
+441234567890
或在英国拨号01234567890

我发现这是有趣的东西我没有测试过但它看起来好像它会工作

<?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.';}?>
    pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$"validateat="onsubmit"

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

对这个话题的大量回复强化了我的直觉——这个问题几乎有无限多的解决方案,没有一个是优雅的。

老实说,我建议你不要尝试验证电话号码。即使你可以编写一个大的、毛茸茸的验证器,允许所有不同的合法格式,它最终会允许几乎任何东西,甚至远程类似于电话号码。

在我看来,最优雅的解决方案是验证最小长度,仅此而已。

对于任何有兴趣用爱尔兰手机号码做类似事情的人来说,这里有一个简单的方法来完成它:

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 valuesvar 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 emptyvar 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 stepvar 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 servervar 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();});

});

来源

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

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

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

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

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

将匹配这些:

+63.917.123.4567+63-917-123-4567+63 917 123 4567+63917123456709171234567

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

在这里测试:http://refiddle.com/1ox

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

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

接受:

+(01) 123 (456) 789 ext555123456*44 123-456-789 [321]123456123456789012345678901234567890123456789012345*****++[](][((( 123456tteexxttppww

拒绝:

mob 07777 7777771234 567 890 after 5pmjohn smith(empty)1234567890123456789012345678901234567890123456911

由您对其进行消毒以供展示。验证后可以是一个数字。

这里有一个在JavaScript中运行良好的。它在一个字符串中,因为这是Dojo小部件所期望的。

它匹配具有可选扩展名的10位北美NANP号码。空格、破折号和句点是可接受的分隔符。

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

如果您只是想验证字段中没有随机垃圾(即来自表单垃圾邮件发送者),则此正则表达式应该做得很好:

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

请注意,它对有多少位数字没有任何特殊规则,或者这些数字中哪些数字是有效的,它只是验证只有数字、括号、破折号、加号、空格、磅、星号、句点、逗号或字母ext存在。

它应该与国际数字和本地化格式兼容。你认为某些地区需要使用方括号、花括号或有角度的括号吗?(目前它们不包括在内)。

如果你想维护每位数的规则(比如在美国地区代码和前缀(交易所代码)必须在200-999之间),祝你好运。维护一个复杂的规则集,它可能在未来的任何时候被世界上任何一个国家过时,听起来都不有趣。

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

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

像上面的答案一样,去掉电话号码中所有的丑陋,这样你就留下了一串数字字符,如果提供了扩展名,则带有'x'

在Python中:

注意: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 = Nonecheck_ext = phone_number.split('x')if len(check_ext) > 1:#there's an extension. Check for errors.if len(check_ext) > 2:return Falsephone_number, ext = check_ext
#we only accept 10 digit phone numbers.if len(phone_number) == 11 and phone_number[0] == '1':#international codephone_number = phone_number[1:]if len(phone_number) != 10:return False
#area_code: XXXxxxxxxx#head:      xxxXXXxxxx#tail:      xxxxxxXXXXarea_code = phone_number[ :3]head      = phone_number[3:6]tail      = phone_number[6: ]
if area_code in BAD_AREA_CODES:return Falseif head[0] == '1':return Falseif head[1:] == '11':return False
#any other ideas?return True

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

我还建议查看“libphonenumber”Google Library。我知道它不是正则表达式,但它完全符合您的要求。

例如,它将认识到:

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

介绍libphonenumber!

使用一个更复杂的例子1-234-567-8901 x1234,你会得到libphonenumber

Validation Results
Result from isPossibleNumber()  trueResult from isValidNumber()     true
Formatting Results:
E164 format                    +12345678901Original format                (234) 567-8901 ext. 123National format                (234) 567-8901 ext. 123International format           +1 234-567-8901 ext. 123Out-of-country format from US  1 (234) 567-8901 ext. 123Out-of-country format from CH  00 1 234-567-8901 ext. 123

因此,您不仅可以了解电话号码是否有效(确实如此),还可以在您的语言环境中获得一致的电话号码格式。

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

Validation Results
Result from isPossibleNumber()  trueResult from isValidNumber()     true
Formatting Results
E164 format                    +61299999999Original format                61 2 9999 9999National format                (02) 9999 9999International format           +61 2 9999 9999Out-of-country format from US  011 61 2 9999 9999Out-of-country format from CH  00 61 2 9999 9999

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

PhoneNumberOfflineGeocoder ResultsLocation        Australia
PhoneNumberToTimeZonesMapper ResultsTime zone(s)    [Australia/Sydney]

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

Validation Results
Result from isPossibleNumber()  trueResult from isValidNumber()     false

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

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

/^(?:(?:\(?(?: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

在$n上,它保存:

  1. 国家指标
  2. 电话号码
  3. 扩展

您可以在https://regex101.com/r/kFzb1s/1上测试它

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

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!';}

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

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

到目前为止,它一直在处理他们抛出的所有内容,但如果出现错误,我会更新这个答案。

正则表达式:

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

PHP函数将所有电话号码替换为tel:链接(以防有人好奇):

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 internationalreturn $return;}

我在另一个SO问题上回答了这个问题,然后决定也将我的答案作为这个线程的答案,因为没有人在解决如何要求/不要求项目,只是分发正则表达式:正则表达式工作错误,匹配意想不到的事情

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

快速备忘单

  • 开始表达式:/^
  • 如果需要空格,请使用:[\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]将需要77或78。
  • $/:结束表达式

这是一个非常棒的模式,它与我需要实现的验证非常匹配。我不是原始作者,但我认为这很值得分享,因为我发现这个问题非常复杂,没有一个简洁或广泛有用的答案。

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

/^\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
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

负数:
926 3 4
8 800 600苹果

来源:http://www.regexr.com/38pvb

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

我发现这工作得很好:

^\(*\+*[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-89011-234-567-8901 x12341-234-567-8901 ext12341 (234) 567-89011.234.567.89011/234/567/8901123456789011-234-567-8901 ext. 1234(+351) 282 433 5050

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

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

使用简单的正则表达式处理各种国际电话号码几乎是不可能的。

您最好使用像这样的服务,他们提供免费的JSON API用于国际电话号码验证,此外,您还可以在每次请求中获得有关国家,位置,运营商和线路类型的一些有用详细信息。

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

有助于国际号码。

说明它接受任何格式的美国手机号码作为输入,并可选择接受第二个参数-如果您希望输出的手机号码格式看起来很漂亮,请设置为true。如果提供的号码不是手机号码,它会简单地返回false。如果检测到手机号码,它会返回整个消毒号码而不是true。

    function isValidMobile(num,format) {if (!format) format=falsevar 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;}}

试试这个(这是印度手机号码验证):

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

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

表达本身:

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

在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)

输出:

1-234-567-89011-234-567-8901 12341-234-567-8901 12341 (234) 567-89011.234.567.89011/234/567/890112345678901

既然有这么多的选项来写一个电话号码,可以测试其中是否有足够的数字,无论它们是如何分离的。我发现9到14位数字对我有用:

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

true:

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

false:

  • 123
  • (1234)1234
  • 9007199254740991
  • 123不会做你告诉我的事
  • +123(456)78.90-98.76#543转210>2>5>3
  • (123)早上456-7890(987)18:00后54-3210找雪莉

如果您确实想支持最后两个示例-只需删除上限:

(\d\D*){9,}

(如果没有上限,则不需要^$

Java为有效电话号码生成REGEX

另一种选择是让Java生成一个REGEX来处理从列表中读取的电话号码的所有变体。这意味着名为validPhoneNumbersFormat的列表(在下面的代码上下文中看到)正在决定哪种电话号码格式是有效的。

注意:这种类型的算法适用于任何处理正则表达式的语言。

生成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);

上下文中的代码片段:

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);}
}

输出:

All valid numbers was matched!
1-234-567-89011-234-567-8901 x12341-234-567-8901 ext1234.........

虽然它不是正则表达式,但您可以使用Python库数据准备中的函数validate_phone()来验证美国电话号码。使用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     True1     True2     True3     True4     True5     True6     True7    False8    FalseName: phone, dtype: bool