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
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
30 回答
我尝试不受限制的正则表达式:
接受:
拒绝:
您需要对其进行消毒以进行显示 . 验证后,它可能是一个数字 .
我写的最简单(虽然我不需要点) .
如下所述,它仅检查字符,而不检查其结构/顺序
我相信Number::Phone::US和Regexp::Common(特别是Regexp::Common::URI::RFC2806的来源)Perl模块可以提供帮助 .
应该更详细地说明问题,以解释验证数字的目的 . 例如,911在美国是有效数字,但911x不是任何x值 . 这样,电话公司可以在您完成拨号时进行计算 . 这个问题有几个变种 . 但是你的正则表达式没有检查区域代码部分,所以这似乎不是一个问题 .
与验证电子邮件地址一样,即使您拥有有效的结果,也无法知道在您尝试之前是否将其分配给某人 .
如果您正在尝试验证用户输入,为什么不将结果标准化并完成它?如果用户输入的号码无法识别为有效号码,请将其保存为输入或删除不可用的字符 . Number::Phone::Normalize Perl模块可能是灵感的源泉 .
/^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i
匹配:
在$ n上,它可以节省:
国家指标
电话号码
扩展
你可以在https://www.regexpal.com/?fam=99127上测试一下
使用单一/简单正则表达式处理国际号码会很困难,请参阅this post了解国际(甚至北美)电话号码的难度 .
您需要解析前几个数字以确定国家/地区代码是什么,然后根据国家/地区采取不同的行动 .
除此之外 - 你提供的列表不包括另一种常见的美国格式 - 从最初的1开始 . 美国的大多数手机都不需要它,除非他们拨打国际电话,否则它将开始困扰年轻一代 .
你已经正确地发现这是一个棘手的问题......
-亚当
你有没看过RegExLib?
输入美国电话号码带来了很多可能性 .
我在一家市场研究公司工作,我们必须及时过滤这些类型的输入 . 你太复杂了 . 只需删除非字母数字字符,然后查看是否有扩展名 .
为了进一步分析,您可以订阅许多提供商中的一个,这些提供商将允许您访问有效号码的数据库,并告诉您它们是固定电话还是移动电话,断开连接等 . 这需要花钱 .
如果您正在谈论表单验证,由于国家和提供商的标准不同,用于验证正确含义以及正确数据的正则表达式将非常复杂 . 它也很难保持最新 .
我将这个问题解释为寻找广泛有效的模式,这种模式可能不是内部一致的 - 例如,有一组有效的数字,但没有验证中继线,交换等到国家代码前缀的有效模式 .
北美很简单,对于国际而言,我更喜欢使用“惯用”模式,该模式涵盖了人们指定和记住数字的方式:
北美模式确保如果包括一个括号,则两者都是 . 国际账户可选择初始''和国家代码 . 在那之后,你就是成语 . 有效匹配将是:
(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
这可能有偏见,因为我的经验仅限于北美,欧洲和亚洲的一小部分 .
我发现这很好用:
它适用于以下数字格式:
确保使用全局AND多行标记来确保 .
链接:http://www.regexr.com/3bp4b
我还建议查看“libphonenumber”Google图书馆 . 我知道它不是正则表达式,但它完全符合您的要求 .
例如,它将认识到:
是可能的数字,但不是有效数字 . 它还支持美国以外的国家 .
Highlights of functionality:
解析/格式化/验证世界上所有国家/地区的电话号码 .
getNumberType
- 根据数字本身获取数字的类型;能够区分固定线路,移动,免费,高级费率,共享成本,VoIP和个人数字(只要可行) .isNumberMatch
- 获得两个数字是否相同的置信度 .getExampleNumber
/getExampleNumberByType
- 为所有国家/地区提供有效的示例号码,并可选择指定所需的示例电话号码类型 .isPossibleNumber
- 通过仅使用长度信息快速猜测数字是否是可能的语音,比完全验证快得多 .isValidNumber
- 使用长度和前缀信息完全验证区域的电话号码 .AsYouTypeFormatter
- 当用户输入每个数字时,即时格式化电话号码 .findNumbers
- 在文本输入中查找数字 .PhoneNumberOfflineGeocoder
- 提供与电话号码相关的地理信息 .例子
电话号码验证的最大问题是它在文化上非常依赖 .
America
(408) 974–2042
是 valid 美国号码(999) 974–2042
是 not a valid 美国号码Australia
0404 999 999
是 valid 澳大利亚号码(02) 9999 9999
也是 valid 澳大利亚号码(09) 9999 9999
是 not a valid 澳大利亚号码正则表达式适用于检查电话号码的格式,但它实际上无法检查电话号码的有效性 .
我建议您跳过一个简单的正则表达式来测试您的电话号码,并使用Google的libphonenumber (link to GitHub project)等库 .
libphonenumber简介!
使用一个更复杂的例子
1-234-567-8901 x1234
,得到the following data out of libphonenumber (link to online demo):因此,您不仅可以了解电话号码是否有效(它是否有效),还可以在您的语言环境中获得一致的电话号码格式 .
作为奖励,
libphonenumber
还有许多数据集来检查电话号码的有效性,因此检查诸如+61299999999
(国际版(02) 9999 9999)之类的数字将作为有效数字返回格式:libphonenumber还为您提供了许多额外的好处,例如 grab 检测到电话号码的位置,以及从电话号码获取时区信息:
但无效的澳大利亚电话号码((09) 9999 9999)表示它不是有效的电话号码 .
Google的版本包含Java和Javascript代码,但人们还为使用Google 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
除非你确定你总是要接受一个语言环境中的数字,并且它们总是采用一种格式,否则我会建议不要为此编写自己的代码,并使用libphonenumber来验证和显示电话号码 .
你可能最好使用蒙面输入 . 这样,用户只能输入数字,您可以根据自己的需要进行格式化 . 我不确定这是否适用于Web应用程序,但如果是这样的话,就会有一个非常简单的jQuery插件,它提供了一些执行此操作的选项 .
http://digitalbush.com/projects/masked-input-plugin/
他们甚至讨论了如何在他们的教程中屏蔽电话号码输入 .
我倾向于同意剥离非数字并且只接受最好的数字 . 也许确保至少存在几个数字,尽管这确实禁止像字母电话号码“ASK-JAKE”这样的东西 .
一些简单的perl表达式可能是:
使用第一个将数字组保持在一起,这可能会给出格式化线索 . 使用第二个来轻松抛出所有非数字 .
是否担心可能需要暂停然后输入更多密钥?或类似555-1212(等待哔哔声)123?
阅读完这些答案之后,看起来似乎没有一个简单的正则表达式可以解析一堆文本并以任何格式提取电话号码(包括带加号和不带加号的国际电话号码) .
这是我最近用于客户端项目的内容,我们必须将所有格式的电话号码转换为tel:links .
到目前为止,它一直在处理他们所做的一切,但如果出现错误,我会更新这个答案 .
正则表达式:
/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/
PHP函数用tel:links替换所有电话号码(万一有人好奇):
到目前为止,这是我最好的尝试 . 它处理上面的格式,但我确定我缺少一些其他可能的格式 .
如果用户想要给你他的电话号码,那么请相信他做对了 . 如果他不想给你,那么强迫他输入一个有效的号码将把他送到竞争对手的网站或让他输入一个适合你的正则表达式的随机字符串 . 我甚至可能会想要查看优质性别行的数量,然后输入 .
我还会将以下任何内容视为网站上的有效条目:
我的直觉这一主题的回复量增强了这种感觉 - 这个问题几乎有无数的解决方案,其中没有一个会变得优雅 .
老实说,我建议你不要试图验证电话号码 . 即使您可以编写一个允许所有不同合法格式的大型毛茸茸的验证器,它最终也会允许几乎任何东西,甚至首先远程类似于电话号码 .
在我看来,最优雅的解决方案是验证最小长度,仅此而已 .
虽然剥离所有空格的答案很简洁,但它并没有真正解决所提出的问题,即找到一个正则表达式 . 例如,我的测试脚本下载网页并使用正则表达式提取所有电话号码 . 既然你还需要一个正则表达式,你也可以让正则表达式完成所有的工作 . 我想出了这个:
这是一个测试它的perl脚本 . 匹配时,$ 1包含区号,$ 2和$ 3包含电话号码,$ 5包含扩展名 . 我的测试脚本从互联网上下载文件并打印其中的所有电话号码 .
Edit:
您可以在正则表达式中将\ W *更改为\ s * \ W?\ s *以将其收紧一点 . 在编写表单时,我没有考虑正则表达式,例如,验证表单上的用户输入,但是这种更改使得为此目的使用正则表达式成为可能 .
这是菲律宾手机号码的简单正则表达式模式:
要么
会匹配这些:
第一个将匹配任何两位数国家代码,而第二个将匹配菲律宾国家代码 .
在这里测试一下:http://refiddle.com/1ox
对于有兴趣与爱尔兰移动电话号码做类似事情的人来说,这是一种直接的方式来实现它:
http://ilovenicii.com/?p=87
PHP
该链接上还有一个JQuery解决方案 .
编辑:
jQuery解决方案:
Source .
事实证明,至少对于北美来说,有一个特定的规范,称为NANP .
您需要准确指定所需内容 . 什么是合法分隔符?空格,破折号和句号?不允许分隔符?可以混合分隔符(例如,0.111-222.3333)吗?如何处理扩展(例如,111-222-3333 x 44444)?特殊号码怎么样,比如911?区号是可选的还是必需的?
这是一个7位或10位数的正则表达式,允许扩展,分隔符是空格,短划线或句点:
这是一个适用于JavaScript的方法 . 它在字符串中,因为这是Dojo小部件所期望的 .
它匹配10位北美NANP号码和可选扩展名 . 空格,短划线和句点是接受的分隔符 .
如果你只是想验证你在该字段中没有随机垃圾(即来自表单垃圾邮件发送者),这个正则表达式应该做得很好:
请注意,对于有多少位数,或者这些数字中有效的数字,它没有任何特殊规则,只是验证只有数字,括号,破折号,加号,空格,磅,星号,句点,逗号或字母
e
,x
,t
在场 .它应该与国际号码和本地化格式兼容 . 您是否预见到某些地区需要允许方括号,卷曲或有角度的括号? (目前不包括在内) .
如果你想保持每位数的规则(例如美国区号和前缀(交换代码)必须在200-999范围内),祝你好运 . 保持一个复杂的规则集,在世界上任何一个国家的未来任何一点都可能过时,听起来并不好玩 .
虽然剥离所有/大多数非数字字符可能在服务器端运行良好(特别是如果您计划将这些值传递给拨号程序),您可能不希望在验证期间抖动用户的输入,特别是如果您希望它们在另一个领域进行更正 .
我觉得这很有意思 . 我没有测试它,但它看起来好像可以工作
更好的选择...只需删除输入中的所有非数字字符('x'和前导'+'标志除外),因为英国倾向于在被要求使用国际前缀时以非标准形式
+44 (0) ...
编写数字(在具体情况,你应该完全丢弃(0)
) .然后,您最终得到如下值:
然后当您显示时,重新格式化您的心灵内容 . 例如
这是一个与我需要实现的验证最匹配的精彩模式 . 我不是原作者,但我认为这很值得分享,因为我发现这个问题非常复杂,而且没有简洁或广泛有用的答案 .
以下正则表达式将捕获各种全球电话号码格式中广泛使用的数字和字符组合:
/^\s*(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/gm
正:
42555.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
原始来源:http://www.regexr.com/38pvb
必须以数字结尾,可以以(或或数字,也可能包含 - (或)开头
我正在努力解决同样的问题,试图让我的应用程序未来证明,但这些人让我朝着正确的方向前进 . 我实际上并没有检查数字本身是否有效,我只是想确保输入了一系列可能有或没有扩展名的数字 .
最糟糕的情况是,如果用户必须从XML文件中提取未格式化的数字,他们仍然只需将数字键入手机的数字键盘
012345678x5
,没有任何理由让它保持漂亮 . 那种RegEx对我来说会是这样的:01234467 extension 123456
01234567x123456
01234567890
替换格式化字符,然后检查剩余的电话有效性 . 在PHP中,
像这样打破复杂的正则表达式可能同样有效,但更简单 .
我在另一个SO问题上回答了这个问题,然后决定将我的答案作为答案包含在这个帖子中,因为没有人在解决如何要求/不需要项目,只是分发正则表达式:Regex working wrong, matching unexpected things
从我在该网站上发布的帖子中,我创建了一个快速指南,帮助任何人根据自己想要的电话号码格式制作自己的正则表达式,我会告诫(就像我在其他网站上所做的那样),如果你限制太多,您可能无法获得理想的结果,并且没有“一刀切”的解决方案来接受世界上所有可能的电话号码 - 只有您决定接受的选择格式 . 使用风险由您自己承担 .
快速备忘单
开始表达式:
/^
如果您想要一个空格,请使用:
[\s]
或\s
如果要要求括号,请使用:
[(]
和[)]
. 使用\(
和\)
是丑陋的,可能让事情变得混乱 .如果您想要任何可选项,请在其后面添加
?
如果需要连字符,只需键入
-
或[-]
即可 . 但是,如果你不把它放在一系列其他字符的第一个或最后一个,你可能需要逃避它:\-
如果要在插槽中接受不同的选项,请在选项周围添加括号:
[-.\s]
将需要连字符,句点或空格 . 最后一个括号后面的问号将使该插槽的所有选项都成为可选项 .\d{3}
:需要一个3位数字:000-999 .[0-9][0-9][0-9]
的简写 .[2-9]
:该插槽需要数字2-9 .(\+|1\s)?
:接受"plus"或1和空格(管道符号,|
,是"or"),并使其成为可选项 . 必须转义"plus"标志 .如果您希望特定数字与插槽匹配,请输入:
[246]
将需要2,4或6.[77|78]
将需要77或78 .$/
:结束表达式请注意,剥离
()
字符不适用于编写常用英国数字的样式:+44 (0) 1234 567890
表示拨打国际号码:+441234567890
或在英国拨打
01234567890