我正在尝试组合一个全面的正则表达式来验证电话号码。理想情况下,它将处理国际格式,但它必须处理美国格式,包括以下内容:
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
1-234-567-8901 x1234
1-234-567-8901 ext1234
1 (234) 567-8901
1.234.567.8901
1/234/567/8901
12345678901
我会用我目前的尝试来回答,但我希望有人有更好和/或更优雅的东西。
+44 (0) ...
更好的选择...只需在输入时去掉所有非数字字符(“x”和前导“+”号除外),请小心,因为英国在被要求使用国际前缀时倾向于以非标准形式书写数字(在那种特定情况下,您应该(0)
完全丢弃)。
然后,您最终会得到如下值:
12345678901
12345678901x1234
345678901x1234
12344678901
12345678901
12345678901
12345678901
+4112345678
+441234567890
然后当你展示时,重新格式化你的内心。例如
1 (234) 567-8901
1 (234) 567-8901 x1234
事实证明,至少对于北美来说,这有一个规范,称为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+))?$
.*
如果用户想给你他们的电话号码,那么相信他们会做对。如果他们不想给你,那么强迫他们输入一个有效的数字会将他们发送到竞争对手的网站,或者让他们输入一个适合你的正则表达式的随机字符串。我什至可能会想查找收费率占星热线的号码,然后输入。
我还将以下任何一项视为网站上的有效条目:
"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 ”谷歌图书馆。我知道它不是正则表达式,但它正是你想要的。
例如,它将认识到:
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 项目)。
使用您更复杂的示例之一,您可以从(链接到在线演示)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) 9999 9999
)之类的数字会返回具有格式的有效数字:
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) 9999 9999
) 返回它不是有效的电话号码。
Validation Results
Result from isPossibleNumber() true
Result from isValidNumber() false
Google 的版本有 Java 和 Javascript 的代码,但人们也为使用 Google i18n 电话号码数据集的其他语言实现了库:
除非你确定你总是会接受来自一个语言环境的号码,并且它们总是采用一种格式,否则我强烈建议不要为此编写自己的代码,并使用 libphonenumber 来验证和显示电话号码。
/^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d+)\)?)[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|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?\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 下载一个文件并打印其中的所有电话号码。
#!/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*))?';
在决定将我的答案作为该线程的答案之前,我在另一个 SO 问题上回答了这个问题,因为没有人解决如何要求/不要求项目,只是分发正则表达式: Regex working wrong, match unexpected things
从我在该网站上的帖子中,我创建了一个快速指南,以帮助任何人为自己想要的电话号码格式制作自己的正则表达式,我会警告(就像我在另一个网站上所做的那样),如果你限制太多,您可能不会得到想要的结果,并且没有“一刀切”的解决方案来接受世界上所有可能的电话号码 - 只有您决定接受的作为您选择的格式。使用风险自负。
/^
[\s]
或\s
[(]
和[)]
. 使用\(
and\)
是丑陋的,并且会使事情变得混乱。?
其后添加-
or [-]
。但是,如果您没有将它放在一系列其他字符中的第一个或最后一个,则可能需要对其进行转义: \-
[-.\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。$/
: 结束表达式我写得最简单(虽然我不需要点)。
^([0-9\(\)\/\+ \-]*)$
如下所述,它仅检查字符,而不检查其结构/顺序
请注意,剥离()
字符不适用于常见的英国号码书写方式:+44 (0) 1234 567890
这意味着拨打国际号码:
+441234567890
或在英国拨打01234567890
如果您只是想验证您在该字段中没有随机垃圾(即来自垃圾邮件发送者),则此正则表达式应该做得很好:
^[0-9+\(\)#\.\s\/ext-]+$
请注意,对于多少位数或这些数字中哪些数字有效,它没有任何特殊规则,它只是验证只有数字、括号、破折号、加号、空格、磅、星号、句点、逗号或字母e
, x
,t
存在。
它应该与国际号码和本地化格式兼容。您是否预见到某些地区需要使用方括号、花括号或尖括号?(目前不包括在内)。
如果您想维护每个数字的规则(例如美国区号和前缀(交换代码)必须在 200-999 范围内),那么祝您好运。维护一套复杂的规则集,世界上任何国家都可能在未来的任何时候过时,这听起来并不有趣。
虽然剥离所有/大多数非数字字符可能在服务器端运行良好(特别是如果您计划将这些值传递给拨号器),但您可能不想在验证期间破坏用户的输入,特别是如果您希望他们这样做在另一个领域进行更正。
你看过RegExLib吗?
输入美国电话号码带回了很多可能性。
这是一个与我需要实现的验证最匹配的精彩模式。我不是原作者,但我认为这很值得分享,因为我发现这个问题非常复杂并且没有简明或广泛有用的答案。
以下正则表达式将捕获各种全球电话号码格式中广泛使用的数字和字符组合:
/^\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-APPLE
我对非限制性正则表达式的尝试:
/^[+#*\(\)\[\]]*([0-9][ ext+-pw#*\(\)\[\]]*){6,45}$/
接受:
+(01) 123 (456) 789 ext555
123456
*44 123-456-789 [321]
123456
123456789012345678901234567890123456789012345
*****++[](][((( 123456tteexxttppww
拒绝:
mob 07777 777777
1234 567 890 after 5pm
john smith
(empty)
1234567890123456789012345678901234567890123456
911
您可以对其进行消毒以进行展示。验证后它可能是一个数字。
我发现这很好用:
^\(*\+*[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
确保使用全局和多行标志来确保。
这是我迄今为止最好的尝试。它处理上述格式,但我确定我错过了一些其他可能的格式。
^\d?(?:(?:[\+]?(?:[\d]{1,3}(?:[ ]+|[\-.])))?[(]?(?:[\d]{3})[\-/)]?(?:[ ]+)?)?(?:[a-zA-Z2-9][a-zA-Z0-9 \-.]{6,})(?:(?:[ ]+|[xX]|(i:ext[\.]?)){1,2}(?:[\d]{1,5}))?$
如果您正在谈论表单验证,那么验证正确含义和正确数据的正则表达式将非常复杂,因为国家和提供商标准不同。也很难保持最新状态。
我将此问题解释为寻找一个广泛有效的模式,该模式可能在内部不一致 - 例如具有一组有效的数字,但未验证中继线、交换机等是否符合国家代码前缀的有效模式.
北美很简单,对于国际,我更喜欢使用“惯用”模式,它涵盖了人们指定和记住他们的数字的方式:
^((((\(\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
这可能是有偏见的,因为我的经验仅限于北美、欧洲和一小部分亚洲。
对这个话题的大量回复强化了我的直觉——这个问题的解决方案几乎是无限的,但没有一个是优雅的。
老实说,我建议您不要尝试验证电话号码。即使你可以编写一个允许所有不同合法格式的大而多毛的验证器,它最终也会允许几乎任何东西,甚至首先是远程类似于电话号码的东西。
在我看来,最优雅的解决方案是验证最小长度,仅此而已。
这是菲律宾手机号码的简单正则表达式模式:
((\+[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
+639171234567
09171234567
第一个将匹配任何两位数的国家代码,而第二个将专门匹配菲律宾国家代码。
在这里测试它:http ://refiddle.com/1ox
您将很难使用单个/简单的正则表达式处理国际号码,请参阅这篇关于国际(甚至北美)电话号码困难的帖子。
您需要解析前几位数字以确定国家/地区代码,然后根据国家/地区采取不同的行动。
除此之外 - 您提供的列表不包括另一种常见的美国格式 - 省略最初的 1。美国的大多数手机不需要它,它会开始让年轻一代感到困惑,除非他们拨打了国际电话。
您已经正确地确定这是一个棘手的问题...
-亚当
阅读完这些答案后,似乎没有一个简单的正则表达式可以解析一堆文本并提取任何格式的电话号码(包括带加号和不带加号的国际电话号码)。
这是我最近用于客户项目的内容,我们必须将任何格式的所有电话号码转换为电话:链接。
到目前为止,它一直在处理他们抛出的所有内容,但如果出现错误,我会更新这个答案。
正则表达式:
/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/
用 tel: 链接替换所有电话号码的 PHP 函数(以防有人好奇):
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 international
return $return;
}
我相信Number::Phone::US和Regexp::Common (尤其是Regexp::Common::URI::RFC2806的来源)Perl 模块可以提供帮助。
这个问题可能应该更详细地说明,以解释验证数字的目的。例如,911 在美国是一个有效的数字,但 911x 不适用于 x 的任何值。这样电话公司就可以在您完成拨号时进行计算。关于这个问题有几种变体。但是您的正则表达式不会检查区号部分,因此这似乎不是问题。
就像验证电子邮件地址一样,即使您有一个有效的结果,在您尝试之前您也无法知道它是否已分配给某人。
如果您正在尝试验证用户输入,为什么不规范化结果并完成它呢?如果用户输入了一个您无法识别为有效数字的数字,请将其保存为已输入的数字或去掉不可替换的字符。Number::Phone::Normalize Perl 模块可能是灵感的来源。
我在一家市场研究公司工作,我们必须一直过滤这些类型的输入。你太复杂了。只需去掉非字母数字字符,看看是否有扩展名。
为了进一步分析,您可以订阅众多提供商之一,这些提供商可以让您访问有效号码的数据库,并告诉您它们是固定电话还是手机、断开连接等。这需要花钱。
对格式化字符进行替换,然后检查剩余的电话有效性。在 PHP 中,
$replace = array( ' ', '-', '/', '(', ')', ',', '.' ); //etc; as needed
preg_match( '/1?[0-9]{10}((ext|x)[0-9]{1,4})?/i', str_replace( $replace, '', $phone_num );
像这样打破复杂的正则表达式同样有效,但要简单得多。
我在同样的问题上苦苦挣扎,试图让我的应用程序面向未来,但这些人让我朝着正确的方向前进。我实际上并没有检查号码本身以查看它是否有效,我只是想确保输入了一系列可能有或没有扩展名的号码。
最坏的情况是,如果用户必须从 XML 文件中提取一个未格式化的号码,他们仍然只是将号码输入到手机的数字键盘012345678x5
中,没有真正的理由让它保持美观。这种RegEx对我来说会是这样的:
\d+ ?\w{0,9} ?\d+
01234467 extension 123456
01234567x123456
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.';
}
?>
为此,您可能会更好地使用 Masked Input。这样,用户只能输入数字,您可以按照您认为合适的方式进行格式化。我不确定这是否适用于 Web 应用程序,但如果是,则有一个非常点击的 jQuery 插件,它提供了一些选项来执行此操作。
http://digitalbush.com/projects/masked-input-plugin/
他们甚至在他们的教程中讨论了如何屏蔽电话号码输入。
这是在 JavaScript 中运行良好的一个。它在一个字符串中,因为这是 Dojo 小部件所期望的。
它与可选扩展名的 10 位北美 NANP 号码匹配。空格、破折号和句点是可接受的分隔符。
"^(\\(?\\d\\d\\d\\)?)( |-|\\.)?\\d\\d\\d( |-|\\.)?\\d{4,4}(( |-|\\.)?[ext\\.]+ ?\\d+)?$"
我倾向于同意剥离非数字并接受那里的东西是最好的。也许是为了确保至少有几个数字存在,尽管这确实禁止了诸如字母电话号码“ASK-JAKE”之类的东西。
几个简单的 perl 表达式可能是:
@f = /(\d+)/g;
tr/0-9//dc;
使用第一个将数字组保持在一起,这可能会提供格式线索。使用第二个简单地折腾所有非数字。
是否担心可能需要暂停然后输入更多键?或者类似 555-1212(等待哔声)123 之类的东西?
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 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();
});
});
来源。
我不建议为此使用正则表达式。
像上面的答案一样,从电话号码中去掉所有丑陋的东西,这样你就剩下一串数字字符,'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 = 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
这涵盖了相当多的内容。它不是正则表达式,但它确实很容易映射到其他语言。
土耳其的工作示例,只需更改
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!';
}
使用简单的正则表达式处理各种国际电话号码几乎是不可能的。
你最好使用像numverify.com这样的服务,他们提供免费的 JSON API 用于国际电话号码验证,而且你会在每个请求中获得一些关于国家、位置、运营商和线路类型的有用详细信息。
寻找String regex = "^\\+(?:[0-9] ?){6,14}[0-9]$";
对国际号码很有帮助。
由于这篇文章没有语言标签,我将给出一个regex
在 python 中使用的解决方案。
表达式本身:
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-8901
1-234-567-8901 1234
1-234-567-8901 1234
1 (234) 567-8901
1.234.567.8901
1/234/567/8901
12345678901
虽然它不是正则表达式,但您可以使用validate_phone()
Python 库DataPrep中的函数来验证美国电话号码。安装它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 True
1 True
2 True
3 True
4 True
5 True
6 True
7 False
8 False
Name: phone, dtype: bool
如果可能的话,我建议使用四个单独的字段——区号、3 位前缀、4 位部分、分机号——以便用户可以分别输入地址的每个部分,并且您可以单独验证每个部分。这样,您不仅可以更轻松地进行验证,还可以将电话号码以更一致的格式存储在数据库中。
注意它将任何格式的美国手机号码作为输入,并且可以选择接受第二个参数 - 如果您希望输出手机号码的格式看起来很漂亮,请设置为 true。如果提供的号码不是手机号码,则简单返回 false。如果检测到手机号码,它会返回整个已清理的号码,而不是 true。
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;
}
}
试试这个(这是用于印度手机号码验证):
if (!phoneNumber.matches("^[6-9]\\d{9}$")) {
return false;
} else {
return true;
}
Java 为有效的电话号码生成正则表达式
另一种选择是让 Java 生成一个 REGEX,它可以对从列表中读取的电话号码的所有变体进行处理。这意味着在代码上下文中看到的名为 validPhoneNumbersFormat 的列表正在决定哪种电话号码格式是有效的。
注意:这种类型的算法适用于任何处理正则表达式的语言。
生成正则表达式的代码片段:
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-8901
1-234-567-8901 x1234
1-234-567-8901 ext1234
...
...
...
由于编写电话号码有很多选择,因此无论它们如何分开,都可以测试其中是否有足够的数字。我发现 9 到 14 位数字对我有用:
^\D*(\d\D*){9,14}$
真的:
错误的:
如果您确实想支持最后两个示例 - 只需删除上限:
(\d\D*){9,}
(^$
如果没有上限,则不需要)
/\b(\d{3}[^\d]{0,2}\d{3}[^\d]{0,2}\d{4})\b/