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


113

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

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


任何正则表达式如何处理服务编号中断之类的错误?就像其他错误一样,只需尝试呼叫并处理无效号码即可。

3
尽管您对正则表达式无法确定这一点是正确的,但每次出站尝试都会浪费时间和资源。快速检查号码可确保明显的虚假呼叫不会阻塞有价值的渠道。
Abtin Forouzandeh,2010年

1
大声笑@ paxdiablo ....我猜1-800-CALL-HELP将通过您的RegExp测试...大声笑
Buhake Sindi 2010年

1
这个问题尚不清楚的是,如果从美国或世界上任何国家/地区拨打电话,这些号码是否必须有效,因为下面的大多数解决方案都没有验证某些有效号码(例如0030 210 12312312-有效希腊号码(来自任何欧盟国家))
Xeroxoid

1
@JonHanna我同意这一点,但另一方面,从UX角度来看,您是否认为如果用户输入00XX ... X编号,则测试应该通过?在某些情况下,用户(即老年人)甚至不知道+是什么,以及如何在数字/电话小键盘上键入。我仍然可以说00XXX是有效的国际号码(即,在用户的上下文中),其中使用了退出代码而不是+。
Xeroxoid

Answers:


96
\+(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替换为标准国际访问代码标识符“ +”,使其成为必填项。我还将国家号码的最小值更改为至少一位数字。

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

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


5
对我来说似乎很明智。我打算用这一个
Sevenearths

17
这是无效的。欧洲电话号码可以以双0开头,开头没有+。因此,如果写为该正则表达式(以及其他答案)不支持的0044 8984 1234,则电话号码,例如:+44 8984 1234(UK)也完全有效。
Xeroxoid

4
结合@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$
SamWhan

1
+1。从UX的角度来看,允许00放在前面可能是有意义的。但从发展和维修点,我会说这是完全正常执行所有的数字都开始+甚至取代00+每次你得到它-特别是考虑到大多数人都知道的+格式(其中大部分国际电话输入字段仍然需要)。另外,它是一种单线修复,并且更具可读性。这种方法还可以确保所有电话号码都采用相同的格式,并使您的验证不易出错,从而使整个流程更易于维护。
milosmns

1
而且,在EDGE(纯GSM)之前的“旧”时代,使用00不会正确发送消息,而以a开头+始终在国际上都可以使用。我们可以发疯,使其变得超级复杂,但有时可能/值得放弃一些限制条件,以使我们的生活更轻松:)
milosmns

66

所有国家代码均由国际电联定义。以下正则表达式基于ITU-T E.164号文件和国际电联操作公告第930 – 15.IV.2009号的附件。它包含所有当前国家代码和保留供将来使用的代码。尽管可以缩短一点,但我决定独立地包含每个代码。

这是针对来自美国的呼叫。对于其他国家/地区,请使用适合该国家/地区拨号计划的内容替换国际访问代码(正则表达式开头的011)

另外,请注意,ITU E.164将完整的国际电话号码的最大长度定义为15位数字。这意味着三位数的国家/地区代码会导致最多十二个附加数字,而一位数的国家/地区代码可能会包含多达十四个其他数字。因此

[0-9]{0,14}$

正则表达式的结尾。

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

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} $


12
几乎是正确的...“ 011”不是国际法规的一部分。这正是美国民众拨打国际电话所需要的。该前缀将根据您拨打电话的地方而有所不同...因此,该前缀不是号码的一部分。
加百利·麦格纳

3
@gmagana-我在回答中提到(第2段)
Abtin Forouzandeh,2010年

1
我的观点是它不是电话号码的一部分。这就像说“ 1”美国国家长途拨号前缀是电话号码的一部分。
加百利·麦格纳

1
@gmagana-当您正确地说它不是电话号码的一部分时,从技术上来说,拨打电话是必需的。
Abtin Forouzandeh,2010年

2
@Roger Pate:我花了一些时间弄清楚这个问题,希望对其他人有用。我还希望其他人可以有更好的解决方案(这就是为什么我没有将自己的答案标记为接受的原因)。
Abtin Forouzandeh,2010年

32

这是进一步的优化。

\+(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
89901 +1(234)56-89 901
+46.234.567.8901
+1 / 234/567/8901


我知道这是一个旧答案,但是是否可以选择将1用作美国数字?
亚当·弗拉蒂诺

您要做的是(i)将“ +”设为可选,并且(ii)将国际代码设为可选。所以放“?” 在+之后和第一个右括号之后。
fezfox '16

@ManosPasgiannis很好,如“后面跟随9或10位数字”所指定。它会在塞浦路斯使用8出现,因此只需通过删除一次\ d \ W *实例并生成最后一个表达式(\ d {1,3})来调整最后一个序列
fezfox

22

您可以使用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();
    }

2
这可能是一个很好的解决方案,但只是为了检查电话号码,使用这个库之前,你必须输入一个庞大的JS量......因为libphonenumber.js需要关闭库 ......这不是一个轻解:/
J. BizMai 2017年

11

这将适用于国际号码;

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}$/

11

我用这个:

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

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


这与大多数国际电话号码格式非常接近。
Feeela

9

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

^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为s [0-9]如果您正则表达式的语法不支持\d



6

修改了@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}$/

奇迹般有效。对于荷兰电话号码也是如此。谢谢!
mauvm

2

到目前为止,给出的所有不同答案都证明了这样做的方式多种多样,但我将在这里投入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 +)$


2

对于那些很棒的答案,请不要提出批评,我只想介绍我用于管理员内容创建者的简单解决方案:

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

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


1

欧洲数字的简单版本,可以匹配诸如0034617393211之类的数字,也可以匹配诸如004401484172842之类的长数字。

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

希望能帮助到你 :·)


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

1
尽管此代码段可以回答问题,但它没有提供任何上下文来解释如何或为什么。考虑添加一两个句子来解释您的答案。
brandonscript

1

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

  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/


1

我在下面使用了这个:

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

格式+ CCC.NNNNNNNNNNxEEEE或00CCC.NNNNNNNNNNxEEEE

拨打国际电话时,电话号码必须以“ +”或“ 00”开头。其中C是1到3位的国家/地区代码,

N最多14位数字,

E是(可选)扩展名。

国家/地区代码后必须加一个加号和加点。仅在提供扩展名时才需要文字“ x”字符。



0

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

如果我能根据ITU E.164编号创建正则表达式,则将对此进行更新。


0

此Regex Expression适用于印度,加拿大,欧洲,新西兰,澳大利亚,美国的电话号码及其国家代码:

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


0

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

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



0

我为欧洲电话号码制作了regexp,它专门针对拨号前缀与号码长度的关系。

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

-4

试试这个,我不知道电话号码是否超过12:

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

1
这会匹配包含国家代码在内的正好 12位数字的数字。这是错误的,因为它没有考虑到整个世界的长度可变性。此外,最大长度实际上是15位数字
tmt

1
@tmt ^(00|\+){1}\d{12,15}$那么呢?
turingtest
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.