【问题标题】:How to validate phone numbers using regex如何使用正则表达式验证电话号码
【发布时间】:2010-09-12 12:29:19
【问题描述】:

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

  • 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

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

【问题讨论】:

标签: regex validation phone-number


【解决方案1】:

更好的选择...只需在输入时去掉所有非数字字符(“x”和前导“+”号除外),由于英国人倾向于以非标准形式+44 (0) ... 写数字时要小心要求使用国际前缀(在这种特定情况下,您应该完全放弃 (0))。

然后,您最终会得到如下值:

 12345678901
 12345678901x1234
 345678901x1234
 12344678901
 12345678901
 12345678901
 12345678901
 +4112345678
 +441234567890

然后,当您展示时,重新格式化您的心满意足。例如

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

【讨论】:

  • 如果允许来自美国以外的数字,格式化代码将是浪费时间。
  • 这很好,但它不能验证输入的内容实际上是电话号码。例如,如果用户没有输入必要的 10 位数字怎么办?这应该与良好的正则表达式验证相结合。
  • 考虑到问题是关于验证 - 这是一个非常糟糕的答案。
  • @PlexQ 我不同意。最初的问题是尝试处理电话号码验证,因为它试图处理所有可能的格式选项。与其尝试解决所有这些问题,不如获取输入并“预先剥离”所有格式绒毛,直到您只有“数字”。这样做解决了 2 个问题 - 测试结果现在很容易,您现在可以确保渲染出来的值都可以一致地格式化。关于“Complicator's Gloves”这个答案的第一条评论是一本很好的读物......有时问题的答案是用不同的方式处理它。
  • 这到底是怎么得到如此高票数的答案?这不会验证任何东西。更糟糕的是所有其他电话号码验证问题都参考了这个......
【解决方案2】:

事实证明,至少对于北美来说,有一个规范,称为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+))?$

【讨论】:

  • 这里没有扩展部分(我让我的用户在单独的字段中输入 ext):^(?:(?:\+?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})$
  • 这是一个只匹配 10 位电话号码的版本(不是 843-1212 之类的 7 位):/(?:(?:\+?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})/
  • 10 位数字在区号周围接受 (),并且不允许以 1 作为国家代码(?:(?:(\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})
  • @StevenSoroka 在过去的两年里,我一直把 Jeffrey Friedl 的书放在我的桌子上,因为正则表达式是我工作的主要部分。真正理解正则表达式需要很长时间。有时,本网站的读者只是在寻找现有的解决方案,而不是自己编写解决方案,尤其是在具有大量极端案例的领域,例如电话号码表示。
  • @fatcat1111 我明白这一点,但这里的大多数回复都是“我也是”类型的一次性正则表达式,可能不适合您的任何极端情况。然后这些最终出现在我尝试使用的所有网站上,我无法输入我的邮政编码、电话号码或电子邮件地址,因为有人使用了半生不熟的正则表达式(例如:+ 是电子邮件地址中的有效字符)。此页面上的最佳响应将用户指向库,而不是纸巾潦草的正则表达式。
【解决方案3】:
.*

如果用户想向您提供他们的电话号码,请相信他们会做对。如果他们不想给你,那么强迫他们输入一个有效的数字会将他们发送到竞争对手的网站,或者让他们输入一个适合你的正则表达式的随机字符串。我什至可能会想查找收费率星座热线的号码,然后输入。

我还将以下任何一项视为网站上的有效条目:

"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"

【讨论】:

  • 我同意这里的观点,但有时当电话号码实际用于符合用户利益的重要事情时,执行验证会很好。这里最好的例子是购买的信用卡授权。如果电话号码错误,可能会导致认证失败。
  • 如果用户不想输入他的电话号码,您可以只允许该字段是可选的,但是如果他们要要求用户输入有效的电话号码是否太多了输入一个?
  • 另外,验证的作用只是提醒人们添加区号等,否则他们可能不会记得添加,但事后不可能猜到。
  • @Pointy 但是正则表达式验证对你没有帮助。实际验证电话号码是否正确的一种也是唯一的方法是实际向其发送消息(如果是移动设备)并确保用户使用某种验证码进行确认。当数字正确性很重要时,您会这样做。其他一切只是为了方便用户防止某些(但不是全部)拼写错误,并且不验证任何内容。
  • 酷。我的电话号码是1' OR 1=1 -- PWNED。见xkcd.com/327owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)
【解决方案4】:

我还建议查看“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 (link to GitHub project) 之类的库。

引入 libphonenumber!

使用你的一个更复杂的例子,1-234-567-8901 x1234,你会得到the following data out of libphonenumber (link to online demo)

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 进行验证和显示电话号码。

【讨论】:

  • 注意到现在还有 Go 端口:github.com/ttacon/libphonenumber
  • 在检查它是否是可能的号码时,您不需要指定国家代码吗?我正在使用 PHP 版本,如果我输入一个英国数字,例如(用实数替换 0)07700000000,我会收到 Missing or invalid default region. 错误。但如果我指定国家代码,它将通过。
  • @BugHunterUK(以及遇到此问题并想知道相同问题的任何人)在解析数字时,您可以指定预期的区域,图书馆将在该地区寻找非国际数字。如果您不指定,它将拒绝任何不是有效国际格式的内容。
  • 请考虑 github.com/nyaruka/phonenumbers,因为它已成为 Google 推荐的“官方”Go 包,而不是 libphonenumber。
  • 我可以确认@BugHunterUK 所说的。花了一些时间到达那里,但结果完全符合预期 - 以任何格式以及所有完全指定的国际格式接受本地号码。
【解决方案5】:

/^(?:(?:\(?(?: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. 国家/地区指标
  2. 电话号码
  3. 分机

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

【讨论】:

  • 这是我见过的最全面的正则表达式。在您删除 ^$ 之前很容易绕过它,否则我可以使用 [111] [111] [1111]111--111--1111 等来绕过它。 (对不起,删除了我最后的评论)
  • 你能重新措辞吗?我无法理解这一点:“在你删除 ^ 和 $ 之前很容易被绕过,否则我可以使用 [111] [111] [1111] 绕过它”。这是否意味着当您使用^$ 时它会验证'[111] [111] [1111]'?
  • ^^^这是一个很好的例子,说明为什么评论线程不应该去聊天。我对这次对话的结果非常感兴趣,并且需要知道这个正则表达式是否足够坚固,可以在我的应用程序中使用。不幸的是,聊天对话现在已经消失了。
  • 说实话,我没去聊天。在多次询问解释后,我一无所获。您可以随时使用您在网上找到的各种数字以多种格式自己尝试。我尝试过的一件事是使用多个电话号码,但如果它们周围有空格,它就不能很好地工作。而且我必须找到一个解决方案来计算数字数量并强制执行特定数量。
  • @heisenberg 感谢您指出,我设法解决了它。此外,我添加了一个与单元测试不同的链接,以确保它可以正常工作。错误是一个不应该存在的?
【解决方案6】:

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

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

【讨论】:

  • 仅供参考,正则表达式也匹配:(4570457-6789,这将是一个很常见的错字。匹配组也会出现偏差:rubular.com/r/TaTP0mHL5c
  • 请注意,这是以北美为中心的——它错过了“44 7911 123456”
【解决方案7】:

在决定将我的答案也作为该线程的答案之前,我在另一个 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)? :接受一个“加号”或一个 1 和一个空格(管道字符 | 是“或”),并将其设为可选。 “加号”必须转义。
  • 如果您希望特定数字与插槽匹配,请输入:[246] 需要 2、4 或 6。(?:77|78)[77|78] 需要 77 或 78。
  • $/ : 结束表达式

【讨论】:

  • 这非常有用,但我怀疑并寻找 {min,max} 表达式。你能帮忙吗?
  • 如果它是我们正在谈论的单个数字(并且您可以根据它进行匹配),请参阅我放在那里的 [2-9] 块。这意味着您的最小值为 2,最大值为 9。相应地进行调整。
【解决方案8】:

我写得最简单(虽然我不需要点)。

^([0-9\(\)\/\+ \-]*)$

如下所述,它只检查字符,而不检查其结构/顺序

【讨论】:

  • 这会验证大量技术上无效的数字。比如,“-- +()()())())))”。学习阅读正则表达式,以便了解自己在做什么。
  • @StevenSoroka 从技术上讲它可能允许很多无效案例,但是当我们考虑用最简单的解决方案帮助用户避免常见错误时,这就是要走的路:)
  • 这也匹配空白,空行
  • @HappyHardik。确实。简单而强大,对于基本验证,让用户输入多个点、破折号、括号或加号。
  • 刚用过,很多方面都错了。例如,英国电话号码可能以 +44 开头,或者电话号码中可能包含 (0)。但这根据您的正则表达式无效。我会推荐@Ismael Miguel 的回答。它工作得很好,我建议你修改你的答案。
【解决方案9】:

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

【讨论】:

【解决方案10】:

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

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

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

它应该与国际号码和本地化格式兼容。您是否预见到某些地区需要使用方括号、花括号或尖括号? (目前不包括在内)。

如果您想维护每个数字的规则(例如美国区号和前缀(交换代码)必须在 200-999 范围内),那么祝您好运。维护一套复杂的规则集,世界上任何国家都可能在未来的任何时候过时,这听起来并不有趣。

虽然去除所有/大多数非数字字符可能在服务器端运行良好(特别是如果您计划将这些值传递给拨号程序),但您可能不想在验证期间破坏用户的输入,尤其是如果您希望他们在另一个领域进行更正。

【讨论】:

    【解决方案11】:

    你看过RegExLib吗?

    输入美国电话号码带来了很多可能性。

    【讨论】:

    • 这看起来像是将晦涩的错误集成到代码中的好方法。
    • 应避免仅链接的答案,因为它们将来可能会中断并使帖子无用。静态解决方案对于维持答案的价值始终是必要的。如果您想推荐超链接,请将其添加为问题下方的评论。
    【解决方案12】:

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

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

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

    【讨论】:

    • 这对扩展有一些有限的支持。它匹配“616-555-1234 x567”,但不匹配“616-555-1234 ext. 567”。
    • 假阳性例如“-------((((((55555555”或“99999999999999999999999”)
    • 它不验证 Nitherland macdonalds 号码 +31 76 596 4192(我只是在测试随机数)
    【解决方案13】:

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

    /^[+#*\(\)\[\]]*([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
    

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

    【讨论】:

      【解决方案14】:

      我发现这很好用:

      ^\(*\+*[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
      

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

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

      【讨论】:

        【解决方案15】:

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

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

        【讨论】:

        • 工作就像一个魅力!感谢分享
        【解决方案16】:

        如果您谈论的是表单验证,那么验证正确含义和正确数据的正则表达式将非常复杂,因为国家和提供商标准各不相同。也很难保持最新状态。

        我将此问题解释为寻找一个广泛有效的模式,该模式可能在内部不一致 - 例如具有一组有效的数字,但未验证中继线、交换等是否符合国家代码前缀。

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

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

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

        【讨论】:

        • 我一直在尝试在我的 javascript 验证脚本中实现上述内容,但我不断收到 invalid quantifier 错误。关于我做错了什么有什么想法吗?
        • 我会添加一个简单的案例,其中电话指定不带符号,但可能是空格和国家代码,在欧洲,本地和手机号码是典型的:676412342、676 46 32 12、676 463 212
        【解决方案17】:

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

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

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

        【讨论】:

        • 在尝试了其中一些并查看了现有数据和用户反馈后,我倾向于同意...
        • 有时您需要进行验证。如果我要发送确认代码,我不能只向垃圾邮件发送者在该字段中输入的任何随机垃圾发送代码。在浪费资源发送消息之前,我想确保该号码可能是一个电话号码。
        【解决方案18】:

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

        ((\+[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

        【讨论】:

        • 谢谢。带有区号(例如 028231234)的固定电话号码怎么样?我想知道区号是否只有 2-3 位数字,它们总是以 0 开头吗?
        【解决方案19】:

        您将很难使用单一/简单的正则表达式处理国际号码,请参阅 this post 了解国际(甚至北美)电话号码的困难。

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

        除此之外-您提供的列表不包括另一种常见的美国格式-省略最初的 1。美国的大多数手机不需要它,它会开始让年轻一代感到困惑,除非他们已经拨打国际电话。

        您已经正确地确定这是一个棘手的问题...

        -亚当

        【讨论】:

        • 不是提供的解决方案。有可能的。仅仅因为它很棘手或复杂并不意味着你应该举起手臂。
        【解决方案20】:

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

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

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

        正则表达式:

        /(\+*\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;
        }
        

        【讨论】:

        • 这个正则表达式匹配+1 1234562222222222222222222222
        • 为什么不直接返回?
        • 误报“999999999999999999999999999999999999999”
        【解决方案21】:

        我相信Number::Phone::USRegexp::Common(尤其是Regexp::Common::URI::RFC2806 的来源)Perl 模块会有所帮助。

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

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

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

        【讨论】:

        • 我要冒昧地说,在这个正则表达式的几乎所有应用程序中,允许 911 作为电话号码可能是个坏主意。不过很好。
        【解决方案22】:

        我在一家市场研究公司工作,我们必须始终过滤这些类型的输入。你太复杂了。只需去掉非字母数字字符,看看是否有扩展名。

        为了进一步分析,您可以订阅众多提供商之一,这些提供商可以让您访问有效号码的数据库,并告诉您它们是固定电话还是手机、断开连接等。这需要花钱。

        【讨论】:

        • 验证? 123%$)*%()$*()#456*()*$#(*(#$@8908 将匹配您提出的解决方案。
        • @PlexQ 555-123-1234, 07777777777, 90210, 01/01/1901 - 用户在通过验证夯实垃圾方面具有创造性。最好不要通过使用过于严格的验证并告诉他们他们错了,从而对那些真正拥有一些奇怪数据的人感到厌烦。
        【解决方案23】:

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

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

        像这样破解复杂的正则表达式同样有效,但要简单得多。

        【讨论】:

          【解决方案24】:

          我发现这很有趣。我还没有测试过,但它看起来好像可以工作

          <?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.';
          }
          ?>
          

          【讨论】:

          【解决方案25】:

          为此,您最好使用屏蔽输入。这样,用户只能输入数字,您可以按照您认为合适的方式进行格式化。我不确定这是否适用于 Web 应用程序,但如果是,则有一个非常点击的 jQuery 插件,它提供了一些执行此操作的选项。

          http://digitalbush.com/projects/masked-input-plugin/

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

          【讨论】:

            【解决方案26】:

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

            它匹配一个 10 位数的北美 NANP 号码和可选的分机号。空格、破折号和句点是可接受的分隔符。

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

            【讨论】:

              【解决方案27】:

              我在同样的问题上苦苦挣扎,试图让我的应用程序经得起未来考验,但这些人让我朝着正确的方向前进。我实际上并没有检查号码本身是否有效,我只是想确保输入了一系列可能有或没有扩展名的号码。

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

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

              【讨论】:

                【解决方案28】:

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

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

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

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

                是否担心可能需要暂停然后输入更多键?还是类似 555-1212(等待哔声)123 之类的?

                【讨论】:

                  【解决方案29】:
                      pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$" 
                      validateat="onsubmit"
                  

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

                  【讨论】:

                    【解决方案30】:

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

                    http://ilovenicii.com/?p=87

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

                    Source.

                    【讨论】:

                      猜你喜欢
                      • 2016-12-09
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多