【问题标题】:What regular expression will match valid international phone numbers?什么正则表达式将匹配有效的国际电话号码?
【发布时间】:2011-01-08 00:08:59
【问题描述】:

在尝试拨号之前,我需要确定电话号码是否有效。电话可以传到世界任何地方。

什么正则表达式将匹配有效的国际电话号码?

【问题讨论】:

  • 正则表达式如何处理诸如停止服务号码之类的错误?只需尝试调用和处理无效号码,就像处理其他错误一样。
  • 虽然您认为正则表达式无法确定这一点是正确的,但每次出站尝试都会消耗时间和资源。对号码进行快速健全性检查可确保明显虚假的电话不会阻塞有价值的频道。
  • LOL @ paxdiablo.... 我猜 1-800-CALL-HELP 会通过你的 RegExp 测试...大声笑
  • 此问题中尚不清楚的是,如果从美国或世界上任何国家/地区拨打电话,这些号码是否必须有效,因为以下大多数解决方案都无法验证某些有效号码(例如 0030 210 12312312 - 从任何欧盟国家拨打的有效希腊号码)
  • @JonHanna 我同意一点,但另一方面,从用户体验的角度来看,你不认为如果用户输入一个 00XX...X 数字,测试应该通过吗?在某些情况下,用户(即老年人)甚至不知道 + 是什么以及如何在数字/电话键盘上输入它。此外,我仍然可以争辩说 00XXX 是一个有效的国际号码(即在用户的上下文中),其中使用了退出代码而不是 +。

标签: regex telephony ivr


【解决方案1】:
\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|
2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|
4[987654310]|3[9643210]|2[70]|7|1)\d{1,14}$

是匹配通用国际电话号码的正确格式。我用标准的国际接入代码标识符“+”替换了以美国陆线为中心的国际接入代码 011,使其成为强制性的。我还将国家号码的最小值更改为至少一位数。

请注意,如果您在手机通讯录中输入这种格式的号码,无论您身在何处,都可以成功拨打通讯录中的任何号码。对于固定电话,请将加号替换为您拨打的国家/地区的国际接入代码。

请注意,这并未考虑国家号码计划规则 - 具体而言,它允许在国家号码计划可能不允许的位置使用 0 和 1,并且还允许某些国家/地区的号码长度大于国家号码计划(例如,美国)。

【讨论】:

  • 对我来说似乎很明智。我要用这个
  • 这是无效的。欧洲电话号码可以以双 0 开头,开头没有 +。因此,电话号码,例如:+44 8984 1234(英国)如果写成 0044 8984 1234 也是完全有效的,这个正则表达式(以及其他答案)不支持。
  • 结合@fezfox 的改进(?)和长度优化:^\+((?:9[679]|8[035789]|6[789]|5[90]|42|3[578]|2[1-689])|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)(?:\W*\d){0,13}\d$
  • +1。从用户体验的角度来看,是的,在前面允许 00 可能是有意义的。从开发和维护的角度来看,我想说强制所有数字以 + 开头,甚至每次得到它时都用 + 替换 00 是完全可以的 - 特别是考虑到大多数人都知道+ 格式(大多数国际电话输入字段无论如何都需要)。此外,它是一个单行修复程序,并且更具可读性。这种方法还可以确保所有电话号码的格式相同,并使您的验证更不容易出错,从而使整个事情更易于维护。
  • 此外,在前 EDGE(普通 GSM)SMS 的“旧”时代,使用00 将无法正确发送消息,而以+ 开头将始终可以在国际范围内使用。我们可以发疯,让它变得超级复杂,但有时可能/值得放弃一些限制来让我们的生活更轻松:)
【解决方案2】:

所有国家代码均由国际电联定义。以下正则表达式基于 ITU-T E.164 和 Annex to ITU Operational Bulletin No. 930 – 15.IV.2009。它包含所有当前的国家代码和保留供将来使用的代码。虽然可以缩短一点,但我决定单独包含每个代码。

这适用于来自美国的呼叫。对于其他国家/地区,请将国际访问代码(正则表达式开头的 011)替换为适合该国家/地区的 dialing plan。

另外,请注意 ITU E.164 将完整国际电话号码的最大长度定义为 15 位。这意味着三位数的国家代码最多可包含 12 个附加数字,而 1 位数的国家代码最多可包含 14 个附加数字。因此

[0-9]{0,14}$

正则表达式的结尾。

最重要的是,此正则表达式并不意味着该号码有效 - 每个国家/地区都定义了自己的内部编号计划。这只确保国家代码有效。

^011(999|998|997|996|995|994|993|992|991| 990|979|978|977|976|975|974|973|972|971|970| 969|968|967|966|965|964|963|962|961|960|899| 898|897|896|895|894|893|892|891|890|889|888| 887|886|885|884|883|882|881|880|879|878|877| 876|875|874|873|872|871|870|859|858|857|856| 855|854|853|852|851|850|839|838|837|836|835| 834|833|832|831|830|809|808|807|806|805|804| 803|802|801|800|699|698|697|696|695|694|693| 692|691|690|689|688|687|686|685|684|683|682| 681|680|679|678|677|676|675|674|673|672|671| 670|599|598|597|596|595|594|593|592|591|590| 509|508|507|506|505|504|503|502|501|500|429| 428|427|426|425|424|423|422|421|420|389|388| 387|386|385|384|383|382|381|380|379|378|377| 376|375|374|373|372|371|370|359|358|357|356| 355|354|353|352|351|350|299|298|297|296|295| 294|293|292|291|290|289|288|287|286|285|284| 283|282|281|280|269|268|267|266|265|264|263| 262|261|260|259|258|257|256|255|254|253|252| 251|250|249|248|247|246|245|244|243|242|241| 240|239|238|237|236|235|234|233|232|231|230| 229|228|227|226|225|224|223|222|221|220|219| 218|217|216|215|214|213|212|211|210|98|95|94| 93|92|91|90|86|84|82|81|66|65|64|63|62|61|60| 58|57|56|55|54|53|52|51|49|48|47|46|45|44|43| 41|40|39|36|34|33|32|31|30|27|20|7|1)[0-9]{0, 14}$

【讨论】:

  • 几乎是对的......“011”不是国际代码的一部分。这正是美国人拨打国际电话需要拨打的号码。该前缀将根据您拨打的位置而改变......因此该前缀不是号码的一部分。
  • @gmagana - 我在回答中提到了这一点(第 2 段)
  • 我的意思是它不是电话号码的一部分。这就像说“1”美国国家长途拨号前缀是电话号码的一部分。
  • @gmagana - 虽然您说得对,它不是电话号码的一部分,但在技术上需要拨打电话。
  • @Roger Pate:我花了一些时间来解决这个问题,我希望它对其他人有用。我还希望其他人可能有更好的解决方案(这就是为什么我没有将自己的答案标记为已接受)。
【解决方案3】:

这是进一步的优化。

\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|
2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|
4[987654310]|3[9643210]|2[70]|7|1)
\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*(\d{1,2})$

(i) 允许使用有效的国际前缀
(ii) 后跟 9 位或 10 位数字,任何类型或位置的分隔符(最后两位数字之间除外)

这将匹配:
+1-234-567-8901
+61-234-567-89-01
+46-234 5678901
+1 (234) 56 89 901
+1 (234) 56-89 901
+46.234.567.8901
+1/234/567/8901

【讨论】:

  • 我知道这是一个旧答案,但有什么选项可以让 1 成为美国数字的可选选项吗?
  • 您要做的是 (i) 将“+”设为可选,并且 (ii) 将国际代码设为可选。所以放置“?”在 + 之后和第一个右括号之后。
  • @ManosPasgiannis 是的,正如指定的“后跟 9 或 10 位数字”。它会出现在你使用 8 的塞浦路斯,所以只需通过删除一次 \d\W* 实例来调整最后一个序列并制作最后一个表达式 (\d{1,3})
【解决方案4】:

您可以使用来自 Google 的库 libphonenumber。

PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
String decodedNumber = null;
PhoneNumber number;
    try {
        number = phoneNumberUtil.parse(encodedHeader, null);
        decodedNumber = phoneNumberUtil.format(number, PhoneNumberFormat.E164);
    } catch (NumberParseException e) {
        e.printStackTrace();
    }

【讨论】:

  • 这可能是一个很好的解决方案,但只是为了检查电话号码,在使用这个库之前,你必须导入大量的 js...因为 libphonenumber.js 需要closure library...不是一个轻松的解决方案:/
  • @J.BizMai 不完全是...闭包库代码被设计为使用闭包编译器进行编译,它可以消除死代码。启用高级优化后,编译后的库可能会非常轻巧且高性能。
【解决方案5】:

修改了@Eric 的正则表达式 - 添加了所有国家代码的列表(从xxxdepy @ Github 获取。 希望对您有所帮助:

/(\+|00)(297|93|244|1264|358|355|376|971|54|374|1684|1268|61|43|994|257|32|229|226|880|359|973|1242|387|590|375|501|1441|591|55|1246|673|975|267|236|1|61|41|56|86|225|237|243|242|682|57|269|238|506|53|5999|61|1345|357|420|49|253|1767|45|1809|1829|1849|213|593|20|291|212|34|372|251|358|679|500|33|298|691|241|44|995|44|233|350|224|590|220|245|240|30|1473|299|502|594|1671|592|852|504|385|509|36|62|44|91|246|353|98|964|354|972|39|1876|44|962|81|76|77|254|996|855|686|1869|82|383|965|856|961|231|218|1758|423|94|266|370|352|371|853|590|212|377|373|261|960|52|692|389|223|356|95|382|976|1670|258|222|1664|596|230|265|60|262|264|687|227|672|234|505|683|31|47|977|674|64|968|92|507|64|51|63|680|675|48|1787|1939|850|351|595|970|689|974|262|40|7|250|966|249|221|65|500|4779|677|232|503|378|252|508|381|211|239|597|421|386|46|268|1721|248|963|1649|235|228|66|992|690|993|670|676|1868|216|90|688|886|255|256|380|598|1|998|3906698|379|1784|58|1284|1340|84|678|681|685|967|27|260|263)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{4,20}$/

【讨论】:

  • 像魅力一样工作。荷兰电话号码也是如此。谢谢!
  • 非常聪明的解决方案! (当然是 +1。)
【解决方案6】:

我用这个:

/([0-9\s\-]{7,})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/

优点:识别 + 或 011 开头,根据需要设置长度,并处理许多扩展约定。 (#,x,ext,extension)

【讨论】:

  • 这个非常接近大多数国际电话号码格式。
【解决方案7】:

这适用于国际号码;

C#:

@"^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$"

JS:

/^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$/

【讨论】:

    【解决方案8】:

    这是您的正则表达式的“优化”版本:

    ^011(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|
    2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|
    4[987654310]|3[9643210]|2[70]|7|1)\d{0,14}$
    

    如果您的正则表达式语法不支持\d,您可以将\ds 替换为[0-9]。

    【讨论】:

      【解决方案9】:

      对于那些出色的答案没有任何批评,我只想向我们的管理员内容创建者展示我使用的简单解决方案:

      ^(\+|00)[1-9][0-9 \-\(\)\.]{7,32}$
      

      强制以加号或两个零开头,并至少使用一点点数字、空格、大括号、减号和点是可选的,没有其他字符。您可以安全地删除所有非数字并在 tel: 输入中使用它。数字将有一个共同的表示形式,我不必担心会受到限制。

      【讨论】:

        【解决方案10】:

        对于 iOS SWIFT,我发现这很有帮助,

        let phoneRegEx = "^((\\+)|(00)|(\\*)|())[0-9]{3,14}((\\#)|())$"
        

        【讨论】:

        • +91 9999999999 失败
        【解决方案11】:

        我在下面使用过这个:

        ^(\+|00)[0-9]{1,3}[0-9]{4,14}(?:x.+)?$
        

        格式 +CCC.NNNNNNNNNNxEEEE 或 00CCC.NNNNNNNNNNxEEEE

        国际电话号码必须以“+”或“00”开头。 其中 C 是 1-3 位国家代码,

        N 最多为 14 位,

        而 E 是(可选的)扩展名。

        国家/地区代码后的前导加号和点是必需的。仅当提供扩展名时才需要文字“x”字符。

        【讨论】:

          【解决方案12】:

          显然有很多方法可以做到这一点,到目前为止给出的所有不同答案都证明了这一点,但我会在这里投入价值 0.02 美元并提供下面的正则表达式,这比几乎所有的都更简洁以上,但也比大多数更彻底。它还有一个很好的副作用,就是将国家代码保留在 1 美元中,将本地号码保留在 2 美元中。

          ^\+(?=\d{5,15}$)(1|2[078]|3[0-469]|4[013-9]|5[1-8]|6[0 -6]|7|8[1-469]|9[0-58]|[2-9]..)(\d+)$

          【讨论】:

            【解决方案13】:

            这是以下最常见电话号码场景的正则表达式。虽然这是从美国的角度针对区号量身定制的,但它适用于国际场景。

            1. 实际数字只能是 10 位数字。
            2. 对于美国号码,区号可以用括号 () 括起来。
            3. 国家代码可以是 1 到 3 位数字。可选地可以在前面加上一个 + 号。
            4. 国家代码、区号和数字的其余部分之间可能有破折号、空格、圆点或没有空格。
            5. 有效的电话号码不能全为零。

              ^(?!\b(0)\1+\b)(\+?\d{1,3}[. -]?)?\(?\d{3}\)?([. -]?)\d{3}\3\d{4}$
              

            解释:

                ^ - start of expression  
                (?!\b(0)\1+\b) - (?!)Negative Look ahead. \b - word boundary around a '0' character. \1 backtrack to previous capturing group (zero). Basically don't match all zeros.  
                (\+?\d{1,3}[. -]?)? - '\+?' plus sign before country code is optional.\d{1,3} - country code can be 1 to 3 digits long. '[. -]?' - spaces,dots and dashes are optional. The last question mark is to make country code optional.  
                \(?\d{3}\)? - '\)?' is to make parentheses optional. \d{3} - match 3 digit area code.  
                ([. -]?) - optional space, dash or dot
                $ - end of expression
            

            更多示例和解释 - https://regex101.com/r/hTH8Ct/2/

            【讨论】:

              【解决方案14】:

              欧洲号码的简单版本,匹配 0034617393211 等数字,但也匹配 004401484172842 等长数字。

              ^0{2}[0-9]{11,}
              

              希望对你有帮助:·)

              【讨论】:

                【解决方案15】:
                public static boolean validateInternationalPhoneNumberFormat(String phone) {
                    StringBuilder sb = new StringBuilder(200);
                
                    // Country code
                    sb.append("^(\\+{1}[\\d]{1,3})?");
                
                    // Area code, with or without parentheses
                    sb.append("([\\s])?(([\\(]{1}[\\d]{2,3}[\\)]{1}[\\s]?)|([\\d]{2,3}[\\s]?))?");
                
                    // Phone number separator can be "-", "." or " "
                
                    // Minimum of 5 digits (for fixed line phones in Solomon Islands)
                    sb.append("\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?");
                
                    // 4 more optional digits
                    sb.append("\\d?[\\-\\.\\s]?\\d?[\\-\\.\\s]?\\d?[\\-\\.\\s]?\\d?$");
                
                    return Pattern.compile(sb.toString()).matcher(phone).find();
                }
                

                【讨论】:

                • 虽然这段代码 sn-p 可以回答这个问题,但它没有提供任何上下文来解释如何或为什么。考虑添加一两句话来解释你的答案。
                【解决方案16】:

                尝试使用以下 API 进行电话号码验证。 这也将返回国家、地区和提供者

                演示 https://libphonenumber.appspot.com/

                混帐 https://github.com/googlei18n/libphonenumber/releases/tag/v8.9.0

                【讨论】:

                  【解决方案17】:

                  国际编号方案基于 ITU E.164 编号方案。我想这就是你的正则表达式的起点。

                  如果我有时间创建一个基于 ITU E.164 编号的正则表达式,我会更新它。

                  【讨论】:

                    【解决方案18】:

                    此正则表达式适用于印度、加拿大、欧洲、新西兰、澳大利亚、美国的电话号码及其国家/地区代码:

                    "^(\+(([0-9]){1,2})[-.])?((((([0-9]){2,3})[-.]){1,2}([0-9]{4,10}))|([0-9]{10}))$"

                    【讨论】:

                      【解决方案19】:

                      这对我有用,但没有 00、001、0011 等前缀:

                      /^\+*(\d{3})*[0-9,\-]{8,}/
                      

                      【讨论】:

                        【解决方案20】:

                        尽管这并不是真正使用 RegExp 来完成工作 - 或者可能正因为如此 - 这对我来说似乎是一个不错的解决方案:https://intl-tel-input.com/node_modules/intl-tel-input/examples/gen/is-valid-number.html

                        【讨论】:

                          【解决方案21】:

                          试试这个,它对我有用。

                          ^(00|\+)[1-9]{1}([0-9][\s]*){9,16}$
                          

                          【讨论】:

                            【解决方案22】:

                            我为欧洲电话号码制作了正则表达式,它专门针对拨号前缀与号码长度。

                            const PhoneEuropeRegExp = () => {
                                // eu phones map https://en.wikipedia.org/wiki/Telephone_numbers_in_Europe
                                const phonesMap = {
                                    "43": [4, 13],
                                    "32": [8, 10],
                                    "359": [7, 9],
                                    "385": [8, 9],
                                    "357": 8,
                                    "420": 9,
                                    "45": 8,
                                    "372": 7,
                                    "358": [5, 12],
                                    "33": 9,
                                    "350": 8,
                                    "49": [3, 12],
                                    "30": 10,
                                    "36": [8, 9],
                                    "354": [7, 9],
                                    "353": [7, 9],
                                    "39": [6, 12],
                                    "371": 8,
                                    "423": [7, 12],
                                    "370": 8,
                                    "352": 8,
                                    "356": 8,
                                    "31": 9,
                                    "47": [4, 12],
                                    "48": 9,
                                    "351": 9,
                                    "40": 9,
                                    "421": 9,
                                    "386": 8,
                                    "34": 9,
                                    "46": [6, 9],
                                };
                                const regExpBuilt = Object.keys(phonesMap)
                                    .reduce(function(prev, key) {
                                        const val = phonesMap[key];
                                        if (Array.isArray(val)) {
                                            prev.push("(\\+" + key + `[0-9]\{${val[0]},${val[1]}\})`);
                                        } else {
                                            prev.push("(\\+" + key + `[0-9]\{${val}\})`);
                                        }
                                        return prev;
                                    }, [])
                                    .join("|");
                                return new RegExp(`^(${regExpBuilt})$`);
                            };
                            
                            alert(PhoneEuropeRegExp().test("+420123456789"))
                            

                            【讨论】:

                              【解决方案23】:

                              它适用于00xx 和+xx:

                              ^(?:00|\+)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{1,14}$
                              

                              【讨论】:

                                【解决方案24】:

                                试试这个,不知道有没有长于12的电话号码:

                                ^(00|\+){1}\d{12}$
                                

                                【讨论】:

                                • 匹配正好 12位数字的号码,包括国家代码。这是错误的,因为它没有考虑到世界各地的长度变化。而且,最大长度其实是15 digits。
                                • @tmt 那么^(00|\+){1}\d{12,15}$ 怎么样?
                                猜你喜欢
                                • 2022-07-22
                                • 2019-05-30
                                • 1970-01-01
                                • 1970-01-01
                                • 2011-05-08
                                • 1970-01-01
                                • 2018-01-23
                                • 1970-01-01
                                相关资源
                                最近更新 更多