Qual expressão regular corresponderá a números de telefone internacionais válidos?

113

Preciso determinar se um número de telefone é válido antes de tentar discá-lo. O telefonema pode ir para qualquer lugar do mundo.

Qual expressão regular corresponderá a números de telefone internacionais válidos?

Abtin Forouzandeh
fonte
Como qualquer regex lida com erros como números fora de serviço? Apenas tente ligar e lidar com o número inválido como faria com outros erros.
3
Embora você esteja certo de que a regex não pode determinar isso, cada tentativa de saída consome tempo e recursos. Fazer uma rápida verificação de integridade do número garante que uma chamada obviamente falsa não bloqueie um canal valioso.
Abtin Forouzandeh
1
LOL @ paxdiablo .... Acho que 1-800-CALL-HELP vai passar no seu teste RegExp ... lol
Buhake Sindi
1
Algo que não está claro nesta questão é se os números têm que ser válidos se chamados dos EUA ou de qualquer país do mundo, porque a maioria das soluções abaixo não validam alguns números válidos (como 0030 210 12312312 - um válido
Telefone
1
@JonHanna Concordo em um ponto, mas por outro lado, da perspectiva de UX, você não acha que se um usuário inserir um número 00XX ... X, o teste deve passar? Há casos em que os usuários (ou seja, pessoas mais velhas) nem sabem o que é o + e como digitá-lo em um teclado numérico / de telefone. Além disso, eu ainda poderia argumentar que 00XXX é um número internacional válido (ou seja, no contexto de um usuário) onde, em vez de +, o código de saída foi usado.
Xeroxoid

Respostas:

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

É o formato correto para corresponder a um número de telefone internacional genérico. Substituí o código de acesso internacional centrado em linha fixa dos EUA 011 pelo identificador de código de acesso internacional padrão '+', tornando-o obrigatório. Também alterei o mínimo do número nacional para pelo menos um dígito.

Observe que se você inserir números neste formato na agenda do seu celular, poderá ligar para qualquer número da agenda, não importa para onde vá. Para linhas fixas, substitua o sinal de mais pelo código de acesso internacional do país de onde você está discando.

Observe que isso NÃO leva em consideração as regras do plano de numeração nacional - especificamente, permite zeros e uns em locais que os planos de numeração nacionais podem não permitir e também permite comprimentos de número maiores do que o plano de numeração nacional para alguns países (por exemplo, os EUA).

Eric
fonte
5
Parece sensato para mim. Vou usar este aqui
Sevenearths
17
Isso não é válido. Os números de telefone europeus podem começar com um duplo 0 sem um + no início. Assim, um número de telefone como: +44 8984 1234 (Reino Unido) também é perfeitamente válido se escrito 0044 8984 1234, que este regexp (e também em outras respostas) não suporta.
Xeroxoid
4
Combinado com as melhorias de @ fezfox (?) E comprimento otimizado:^\+((?: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. Do ponto de vista da UX, sim, pode fazer sentido permitir 00na frente. Do ponto de vista de desenvolvimento e manutenção, eu diria que é perfeitamente normal forçar todos os números para começar +ou até mesmo substituir 00um +cada vez que você o obtiver - especialmente porque a maioria das pessoas está ciente do +formato (que a maioria dos campos internacionais de entrada de telefone exigir de qualquer maneira). Além disso, é uma correção de uma linha e muito mais legível. Essa abordagem também garantiria que todos os números de telefone estivessem no mesmo formato e tornaria sua validação muito menos sujeita a erros, tornando tudo mais fácil de manter.
milosmns
1
E também, nos "velhos" dias do SMS pré-EDGE (GSM simples), usar 00não enviava a mensagem corretamente, ao passo que começar com a +sempre funcionaria internacionalmente. Podemos enlouquecer e torná-lo super complexo, mas às vezes é possível / vale a pena abandonar algumas restrições para tornar nossas vidas mais fáceis :)
milosmns
66

Todos os códigos de país são definidos pela ITU. O seguinte regex é baseado no ITU-T E.164 e no Anexo do Boletim Operacional ITU No. 930 - 15.IV.2009 . Ele contém todos os códigos de país atuais e códigos reservados para uso futuro. Embora pudesse ser um pouco abreviado, decidi incluir cada código de forma independente.

Isso é para chamadas originadas dos EUA. Para outros países, substitua o código de acesso internacional (o 011 no início da regex) pelo que for apropriado para o plano de discagem daquele país .

Além disso, observe que o ITU E.164 define o comprimento máximo de um número de telefone internacional completo para 15 dígitos. Isso significa que um código de país de três dígitos resulta em até 12 dígitos adicionais, e um código de país de 1 dígito pode conter até 14 dígitos adicionais. Daí o

[0-9]{0,14}$

ao final da regex.

Mais importante ainda, esta regex não significa que o número é válido - cada país define seu próprio plano de numeração interno. Isso apenas garante que o código do país seja válido.

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

Abtin Forouzandeh
fonte
12
Quase acertou ... "011" não faz parte de um código internacional. É exatamente o que as pessoas nos EUA precisam discar para fazer uma chamada internacional. Esse prefixo mudará dependendo de onde você discar ... Portanto, esse prefixo NÃO faz parte do número.
Gabriel Magana
3
@gmagana - Menciono isso em minha resposta (parágrafo 2)
Abtin Forouzandeh
1
Meu ponto é que não faz parte do número de telefone. É como dizer que o prefixo "1" de discagem de longa distância nacional dos EUA faz parte do número de telefone.
Gabriel Magana
1
@gmagana - embora você esteja certo de que não faz parte do número de telefone, é tecnicamente necessário fazer a chamada.
Abtin Forouzandeh
2
@Roger Pate: Passei um pouco de tempo tentando descobrir isso e espero que seja útil para outras pessoas. Também esperava que outra pessoa tivesse uma solução melhor (por isso não marquei minha própria resposta como aceita).
Abtin Forouzandeh
32

Esta é mais uma otimização.

\+(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) permite prefixos internacionais válidos
(ii) seguidos de 9 ou 10 dígitos, com qualquer tipo ou colocação de delimitadores (exceto entre os dois últimos dígitos)

Isso corresponderá a:
+ 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

fezfox
fonte
Eu sei que esta é uma resposta antiga, mas existe alguma opção para tornar o 1 opcional para números americanos?
Adam Fratino
O que você deseja fazer é (i) tornar o "+" opcional e (ii) o código internacional opcional. Então coloque "?" após o + e após o primeiro colchete de fechamento.
fezfox
@ManosPasgiannis bem sim, conforme especificado "seguido por 9 ou 10 dígitos". Apareceria em chipre que você usa 8, então apenas ajuste a última sequência removendo uma instância de \ d \ W * e faça a última expressão (\ d {1,3})
fezfox
22

Você pode usar a biblioteca libphonenumber do Google.

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();
    }
Paulo fidalgo
fonte
2
Pode ser uma boa solução, mas apenas para verificar os números de telefone, antes de usar esta biblioteca, você tem que importar uma grande quantidade de js ... porque libphonenumber.js precisa de uma biblioteca de encerramento ... não é uma solução leve: /
J. BizMai
11

Isso funcionará para números internacionais;

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}$/
MADol
fonte
11

Eu uso este:

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

Vantagens: reconhece + ou 011 inícios, permite que seja o tempo que for necessário e lida com muitas convenções de extensão. (#, x, ext, extensão)

TOBlender
fonte
Este chega muito perto da maioria dos formatos de número de telefone internacionais.
feeela
9

Esta é uma versão "otimizada" do seu regex:

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

Você pode substituir o \ds por [0-9]se sua sintaxe regex não for compatível \d.

Laurence Gonsalves
fonte
7

Para iOS SWIFT , achei isso útil,

let phoneRegEx = "^((\\+)|(00)|(\\*)|())[0-9]{3,14}((\\#)|())$"
Mohammad Zaid Pathan
fonte
falhou por +91 9999999999
Sahil Mahajan
6

Expressão regular modificada de @ Eric - adicionada uma lista de todos os códigos de país (consegui-los em xxxdepy @ Github . Espero que seja útil:

/(\+|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}$/
Dev
fonte
Funciona como um encanto. Para números de telefone holandeses também. Obrigado!
mauvm
2

Obviamente, há uma infinidade de maneiras de fazer isso, conforme evidenciado por todas as diferentes respostas dadas até agora, mas vou jogar meu valor de $ 0,02 aqui e fornecer a regex abaixo, que é um pouco mais concisa do que quase todas as anteriores , mas também mais completo do que a maioria. Também tem o bom efeito colateral de deixar o código do país em $ 1 e o número local em $ 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 +) $

trekinaz
fonte
2

Sem críticas em relação a essas ótimas respostas, só quero apresentar a solução simples que uso para nossos criadores de conteúdo administrativo:

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

Forçar iniciar com mais ou dois zeros e usar pelo menos um pouco de números, espaço em branco, colchetes, menos e ponto é opcional e nenhum outro caractere. Você pode remover com segurança todos os não-números e usar isso em uma entrada tel :. Os números terão uma forma comum de representação e não preciso me preocupar em ser tão restritivo.

Blackbam
fonte
1

Uma versão simples para números europeus, que corresponde a números como 0034617393211, mas também a números longos como 004401484172842.

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

Espero que ajude :·)

Roc Boronat
fonte
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();
}
Cássio
fonte
1
Embora este trecho de código possa responder à pergunta, ele não fornece nenhum contexto para explicar como ou por quê. Considere adicionar uma frase ou duas para explicar sua resposta.
brandonscript
1

Aqui está um regex para os seguintes cenários de número de telefone mais comuns. Embora seja adaptado a partir de uma perspectiva dos EUA para códigos de área, funciona para cenários internacionais.

  1. O número real deve ter apenas 10 dígitos.
  2. Para números dos EUA, o código de área pode estar entre parênteses ().
  3. O código do país pode ter de 1 a 3 dígitos. Opcionalmente, pode ser precedido por um sinal +.
  4. Pode haver travessões, espaços, pontos ou nenhum espaço entre o código do país, código de área e o resto do número.
  5. Um número de telefone válido não pode conter apenas zeros.

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

Explicação:

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

Mais exemplos e explicações - https://regex101.com/r/hTH8Ct/2/

Appy
fonte
1

Eu usei isso abaixo:

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

O formato + CCC.NNNNNNNNNNxEEEE ou 00CCC.NNNNNNNNNNxEEEE

O número de telefone deve começar com '+' ou '00' para uma chamada internacional. onde C é o código do país de 1 a 3 dígitos,

N tem até 14 dígitos,

e E é a extensão (opcional).

O sinal de adição inicial e o ponto após o código do país são obrigatórios. O caractere literal “x” é necessário apenas se uma extensão for fornecida.

Rousonur Jaman
fonte
0

O plano de numeração internacional é baseado no ITU E.164 plano de numeração . Acho que esse é o ponto de partida para sua expressão regular.

Vou atualizar isso se conseguir criar uma expressão regular com base na numeração ITU E.164.

Buhake Sindi
fonte
0

Esta expressão Regex funciona para os números de telefone da Índia, Canadá, Europa, Nova Zelândia, Austrália, Estados Unidos, junto com seus códigos de país:

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

Harsha Garg
fonte
0

Isso funciona para mim, sem o prefixo 00, 001, 0011 etc:

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

Experimente, funciona para mim.

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

Fiz o regexp para números de telefone europeus e é específico para prefixo de discagem vs comprimento do número.

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"))
luky
fonte
-4

Experimente, não sei se existe algum número de telefone maior que 12:

^(00|\+){1}\d{12}$
MKYuones
fonte
1
Corresponde a números com exatamente 12 dígitos, incluindo o código do país. Isso está errado porque não leva em conta a variabilidade de comprimento em todo o mundo. Além disso, o comprimento máximo é de 15 dígitos .
tmt
1
@tmt Que tal ^(00|\+){1}\d{12,15}$então?
testado em