我试图把一个全面的正则表达式放在一起来验证电话号码。理想情况下,它可以处理国际格式,但它必须处理美国格式,包括以下内容:
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
我会用我目前的尝试来回答,但我希望有人有更好的和/或更优雅的东西。
当前回答
我不建议使用正则表达式。
和上面的答案一样,去掉所有难看的电话号码,这样你就只剩下一串数字字符,如果提供扩展名的话,还会有一个'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
这涵盖了相当多的内容。它不是一个正则表达式,但它确实很容易映射到其他语言。
其他回答
注意:它以任何格式的美国手机号码作为输入,并可选地接受第二个参数-如果您希望输出的手机号码格式看起来更漂亮,则设置为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;
}
}
你看过RegExLib了吗?
输入一个美国的电话号码,你会发现很多可能性。
我还建议查看“libphonenumber”谷歌库。我知道它不是正则表达式,但它确实是你想要的。
例如,它会识别:
15555555555
是可能的数字,但不是有效数字。它还支持美国以外的国家。
功能亮点:
Parsing/formatting/validating phone numbers for all countries/regions of the world. getNumberType - gets the type of the number based on the number itself; able to distinguish Fixed-line, Mobile, Toll-free, Premium Rate, Shared Cost, VoIP and Personal Numbers (whenever feasible). isNumberMatch - gets a confidence level on whether two numbers could be the same. getExampleNumber/getExampleNumberByType - provides valid example numbers for all countries/regions, with the option of specifying which type of example phone number is needed. isPossibleNumber - quickly guessing whether a number is a possible phonenumber by using only the length information, much faster than a full validation. isValidNumber - full validation of a phone number for a region using length and prefix information. AsYouTypeFormatter - formats phone numbers on-the-fly when users enter each digit. findNumbers - finds numbers in text input. PhoneNumberOfflineGeocoder - provides geographical information related to a phone number.
例子
电话号码验证最大的问题是它非常依赖文化。
美国 (408) 974-2042是有效的美国号码 (999) 974-2042不是有效的美国号码 澳大利亚 0404 999 999是一个有效的澳大利亚号码 (02) 9999 9999也是一个有效的澳大利亚号码 (09) 9999 9999不是有效的澳大利亚号码
正则表达式可以用于检查电话号码的格式,但它不能真正地检查电话号码的有效性。
我建议跳过简单的正则表达式来测试你的电话号码,并使用一个库,如谷歌的libphonenumber(链接到GitHub项目)。
引入libphonenumber !
使用一个更复杂的示例,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)99999999的国际版本)这样的号码,返回一个带有格式的有效号码:
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)99999999)返回它不是一个有效的电话号码。
Validation Results
Result from isPossibleNumber() true
Result from isValidNumber() false
谷歌的版本有Java和Javascript的代码,但人们也实现了使用谷歌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 灵丹妙药:https://github.com/socialpaymentsbv/ex_phone_number
除非您确定始终接受来自一个地区的数字,并且始终采用同一种格式,否则我强烈建议不要为此编写自己的代码,并使用libphonenumber来验证和显示电话号码。
更好的选择……只要去掉输入中的所有非数字字符(除了“x”和前导的“+”符号),注意,因为英国人倾向于用非标准形式的+44(0)写数字……当要求使用国际前缀时(在这种特定情况下,应该完全丢弃(0))。
然后,你会得到这样的值:
12345678901
12345678901x1234
345678901x1234
12344678901
12345678901
12345678901
12345678901
+4112345678
+441234567890
然后,当你显示,重新格式化为您的心脏内容。如。
1 (234) 567-8901
1 (234) 567-8901 x1234
我也在为同样的问题而挣扎,试图让我的应用程序经得起未来的考验,但这些人让我走上了正确的方向。我实际上并不是在检查数字本身,看它是否有效,我只是试图确保输入的一系列数字可能有或没有扩展名。
最坏的情况是,如果用户必须从XML文件中提取一个未格式化的数字,他们仍然只是将数字输入到手机的数字pad 012345678x5中,没有真正的理由保持它的美观。这种RegEx对我来说是这样的:
\d+ ?\w{0,9} ?\d+
01234467分机号123456 01234567 x123456 01234567890