使用 php/regex 验证美国电话号码
编辑: 我混合并修改了下面给出的两个答案,以形成完整的功能,该功能现在可以完成我想要的功能,然后是一些......所以我想我会发布它以防其他人来寻找同样的东西。
/*
* Function to analyze string against many popular formatting styles of phone numbers
* Also breaks phone number into it's respective components
* 3-digit area code, 3-digit exchange code, 4-digit subscriber number
* After which it validates the 10 digit US number against NANPA guidelines
*/
function validPhone($phone) {
$format_pattern = '/^(?:(?:\((?=\d{3}\)))?(\d{3})(?:(?<=\(\d{3})\))?[\s.\/-]?)?(\d{3})[\s\.\/-]?(\d{4})\s?(?:(?:(?:(?:e|x|ex|ext)\.?\:?|extension\:?)\s?)(?=\d+)(\d+))?$/';
$nanpa_pattern = '/^(?:1)?(?(?!(37|96))[2-9][0-8][0-9](?<!(11)))?[2-9][0-9]{2}(?<!(11))[0-9]{4}(?<!(555(01([0-9][0-9])|1212)))$/';
//Set array of variables to false initially
$valid = array(
'format' => false,
'nanpa' => false,
'ext' => false,
'all' => false
);
//Check data against the format analyzer
if(preg_match($format_pattern, $phone, $matchset)) {
$valid['format'] = true;
}
//If formatted properly, continue
if($valid['format']) {
//Set array of new components
$components = array(
'ac' => $matchset[1], //area code
'xc' => $matchset[2], //exchange code
'sn' => $matchset[3], //subscriber number
'xn' => $matchset[4], //extension number
);
//Set array of number variants
$numbers = array(
'original' => $matchset[0],
'stripped' => substr(preg_replace('[\D]', '', $matchset[0]), 0, 10)
);
//Now let's check the first ten digits against NANPA standards
if(preg_match($nanpa_pattern, $numbers['stripped'])) {
$valid['nanpa'] = true;
}
//If the NANPA guidelines have been met, continue
if($valid['nanpa']) {
if(!empty($components['xn'])) {
if(preg_match('/^[\d]{1,6}$/', $components['xn'])) {
$valid['ext'] = true;
}
}
else {
$valid['ext'] = true;
}
}
//If the extension number is valid or non-existent, continue
if($valid['ext']) {
$valid['all'] = true;
}
}
return $valid['all'];
}
EDIT: I've mixed and modified two of the answers given below to form the full function which now does what I had wanted and then some... So I figured I'd post it here in case anyone else comes looking for this same thing.
/*
* Function to analyze string against many popular formatting styles of phone numbers
* Also breaks phone number into it's respective components
* 3-digit area code, 3-digit exchange code, 4-digit subscriber number
* After which it validates the 10 digit US number against NANPA guidelines
*/
function validPhone($phone) {
$format_pattern = '/^(?:(?:\((?=\d{3}\)))?(\d{3})(?:(?<=\(\d{3})\))?[\s.\/-]?)?(\d{3})[\s\.\/-]?(\d{4})\s?(?:(?:(?:(?:e|x|ex|ext)\.?\:?|extension\:?)\s?)(?=\d+)(\d+))?$/';
$nanpa_pattern = '/^(?:1)?(?(?!(37|96))[2-9][0-8][0-9](?<!(11)))?[2-9][0-9]{2}(?<!(11))[0-9]{4}(?<!(555(01([0-9][0-9])|1212)))$/';
//Set array of variables to false initially
$valid = array(
'format' => false,
'nanpa' => false,
'ext' => false,
'all' => false
);
//Check data against the format analyzer
if(preg_match($format_pattern, $phone, $matchset)) {
$valid['format'] = true;
}
//If formatted properly, continue
if($valid['format']) {
//Set array of new components
$components = array(
'ac' => $matchset[1], //area code
'xc' => $matchset[2], //exchange code
'sn' => $matchset[3], //subscriber number
'xn' => $matchset[4], //extension number
);
//Set array of number variants
$numbers = array(
'original' => $matchset[0],
'stripped' => substr(preg_replace('[\D]', '', $matchset[0]), 0, 10)
);
//Now let's check the first ten digits against NANPA standards
if(preg_match($nanpa_pattern, $numbers['stripped'])) {
$valid['nanpa'] = true;
}
//If the NANPA guidelines have been met, continue
if($valid['nanpa']) {
if(!empty($components['xn'])) {
if(preg_match('/^[\d]{1,6}$/', $components['xn'])) {
$valid['ext'] = true;
}
}
else {
$valid['ext'] = true;
}
}
//If the extension number is valid or non-existent, continue
if($valid['ext']) {
$valid['all'] = true;
}
}
return $valid['all'];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用先行断言解决此问题。基本上我们所说的是我想要一系列特定的字母(e、ex、ext、x、扩展名),后跟一个或多个数字。但我们还想涵盖根本没有扩展的情况。
这是正则表达式的更新,也可以解决您的评论。我已在实际代码中添加了解释。
输出:
You can resolve this using a lookahead assertion. Basically what we're saying is I want a series of specific letters, (e, ex, ext, x, extension) followed by one or more number. But we also want to cover the case where there's no extension at all.
Here's an update with regex that resolves your comment here as well. I've added the explanation in the actual code.
And The Output:
当前的 REGEX
有很多问题,导致它匹配以下所有内容:
(0./ -000 ./-0000 x00000000000000000000000)
()./1234567890123456789012345678901234567890
\)\-555/1212 x
我认为这个 REGEX 更接近您正在寻找的内容:
或者,分解:
此修改提供了一些改进。
preg_match()
中的 $matches 中。它有一些小限制。它们可能不重要,但在这里被注意到。
NANPA 规则改编自以下正则表达式,可在此处找到: http://blogchuck.com/2010/01/php-regex-for-validating-phone-numbers/
The current REGEX
has a lot of issues, resulting in it matching all of the following, among others:
(0./ -000 ./-0000 x00000000000000000000000)
()./1234567890123456789012345678901234567890
\)\-555/1212 x
I think this REGEX is closer to what you're looking for:
or, exploded:
This modification provides several improvements.
preg_match()
.It has a few minor limitations. They're probably unimportant, but are being noted here.
The NANPA rules are adapted from the following REGEX, found here: http://blogchuck.com/2010/01/php-regex-for-validating-phone-numbers/
为什么不将任何一系列字母转换为“x”。这样你就可以将所有可能性转换为“x”。
或者
检查 3digits、3digits、4digits、1orMoreDigits 并忽略
正则表达式之间的任何其他字符:
<代码>([0-9]{3}).*?([0-9]{3}).*?([0-9]{4}).+?([0-9]{1 ,})
Why not convert any series of letters to be "x". Then that way you would have all possibilities converted to be "x".
OR
Check for 3digits, 3digits, 4digits, 1orMoreDigits and disregard any other characters inbetween
Regex:
([0-9]{3}).*?([0-9]{3}).*?([0-9]{4}).+?([0-9]{1,})
或者,您可以使用一些非常简单直接的 JavaScript 来强制用户以更指定的格式输入。屏蔽输入插件 ( http://digitalbush.com/projects/masked-input-plugin/ ) for jQuery 允许您将 HTML 输入屏蔽为电话号码,只允许用户输入 xxx-xxx-xxxx 格式的号码。它不能解决您的扩展问题,但它确实提供了更清晰的用户体验。
Alternatively, you could use some pretty simple and straightforward JavaScript to force the user to enter in a much more specified format. The Masked Input Plugin ( http://digitalbush.com/projects/masked-input-plugin/ ) for jQuery allows you to mask an HTML input as a telephone number, only allowing the person to enter a number in the format xxx-xxx-xxxx. It doesn't solve your extension issues, but it does provide for a much cleaner user experience.
好吧,您可以修改正则表达式,但这不会很好 - 您应该允许“extn”吗? “程度”怎么说? “然后你必须拨打”怎么样?
我认为“正确”的方法是添加一个单独的数字扩展表单框。
但如果你真的想要正则表达式,我想我已经修复了它。提示:单个字符不需要
[x]
,x
即可。您允许使用点、斜线、短划线和空白字符。您应该只允许这些选项之一。您需要更新对
$matches
的引用;有用的组现在是 0、2 和 4。PS 这是未经测试的,因为我没有 PHP 运行的参考实现。抱歉,如果您发现任何错误,请告诉我,我会尽力修复它们。
编辑
这比我可以这里总结得更好。
Well, you could modify the regex, but it won't be very nice -- should you allow "extn"? How about "extentn"? How about "and then you have to dial"?
I think the "right" way to do this is to add a separate, numerical, extension form box.
But if you really want the regex, I think I've fixed it up. Hint: you don't need
[x]
for a single character,x
will do.You allowed a dot, a slash, a dash, and a whitespace character. You should allow only one of these options. You'll need to update the references to
$matches
; the useful groups are now 0, 2, and 4.P.S. This is untested, since I don't have a reference implentation of PHP running. Apologies for mistakes, please let me know if you find any and I'll try to fix them.
Edit
This is summed up much better than I can here.