Como validar números de telefone usando regex


920

Estou tentando montar um regex abrangente para validar números de telefone. Idealmente, ele lidaria com formatos internacionais, mas deve lidar com os formatos dos EUA, incluindo o seguinte:

  • 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

Responderei com minha tentativa atual, mas espero que alguém tenha algo melhor e / ou mais elegante.


3
BTW, você deve especificar qual idioma você está usando. Nem todos os mecanismos de expressão regular têm a mesma sintaxe.
AndrewJFord 23/09/08

9
Parece que você deixou de lado a opção +1 em vez de apenas 1, embora a resposta cubra esse caso.
Eric

153
Nem todos os números de telefone dos EUA exigem 555neles além de 911?
Andrew Grimm

41
Pelo contrário, o prefixo 555 é reservado para números de telefone falsificados. É garantido que esses números não se conectem a um número de telefone real, por isso são frequentemente usados ​​na televisão e nos filmes para garantir que um espectador não tente ligar para o número e acabe assediando alguns inocentes pobres.
rushinge

49
@rushinge Embora isso fosse verdade décadas atrás, não é mais verdade . O prefixo 555 ainda é especial, mas apenas um pequeno intervalo de números é garantido para terminar sem a conexão 555-0100 a 555-0199. Mas tenho certeza de que Andrew estava brincando de qualquer maneira.
Adam Davis

Respostas:


515

Melhor opção ... apenas retire todos os caracteres que não sejam dígitos na entrada (exceto os sinais 'x' e '+' iniciais), tendo o cuidado de manter a tendência britânica de escrever números no formato não-padrão +44 (0) ...quando solicitado a usar o prefixo internacional (nesse caso específico, você deve descartar (0)totalmente).

Então, você acaba com valores como:

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

Então, quando você exibir, reformate o conteúdo do seu coração. por exemplo

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

35
O código de formatação será uma perda de tempo se os números puderem vir de fora dos EUA.
21119 Daniel Earwicker

26
Isso é bom e tudo, mas não valida o que foi digitado, na verdade, era um número de telefone. Por exemplo, e se o usuário não digitar os 10 dígitos necessários? Isso deve ser combinado com boa validação de regex.
Hugh Jeffner

108
Considerando que a pergunta era sobre validação - essa é uma resposta realmente muito ruim.
PlexQ

15
@PlexQ Eu discordo. O problema original está tentando lidar com a validação de número de telefone porque estava tentando lidar com todas as opções de formatação possíveis. Em vez de tentar resolver tudo isso, pegue a entrada e remova-a de todos os tipos de formatação até obter apenas o "número". Isso resolve dois problemas - agora é fácil testar o resultado e agora você pode garantir que os valores renderizados novamente para exibição possam ser formatados de forma consistente. O primeiro comentário desta resposta sobre as "Luvas do complicador" é uma boa leitura ... às vezes a resposta para um problema é abordá-lo de maneira diferente.
scunliffe

29
Como diabos é essa resposta altamente votada? Isso não valida nada. O pior é todas as outras questões de validação de número de telefone referenciar este ...
jlars62

303

Acontece que há uma espécie de especificação para isso, pelo menos para a América do Norte, chamada NANP .

Você precisa especificar exatamente o que deseja. O que são delimitadores legais? Espaços, traços e pontos? Nenhum delimitador permitido? Pode-se misturar delimitadores (por exemplo, + 0,1111-222,3333)? Como as extensões (por exemplo, 111-222-3333 x 44444) serão tratadas? E os números especiais, como o 911? O código de área será opcional ou obrigatório?

Aqui está uma regex para um número de 7 ou 10 dígitos, com extensões permitidas, delimitadores são espaços, traços ou pontos:

^(?:(?:\+?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+))?$

7
aqui está sem a seção de extensão (eu faço meus usuários digitar ext em um campo separado): ^ (?: (?: \ +? 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}) $
aarona

18
Aqui está uma versão que corresponde apenas 10 números de telefone dígitos (não 7 dígitos como 843-1212): /(?:(?:\+?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})/
Brian Armstrong

8
10 dígitos aceitam () em torno do código de área e não permitem preceder 1 como código do paí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})
Brooke.

5
@StevenSoroka Eu tenho o livro de Jeffrey Friedl ao meu lado na minha mesa nos últimos dois anos, pois expressões regulares são uma parte importante do meu trabalho. Demora um bom tempo para realmente entender expressões regulares. Às vezes, os leitores deste site estão simplesmente procurando uma solução existente, em vez de escreverem seus próprios, especialmente em domínios com muitos casos de canto, como representações de números de telefone.
Justin R.

7
@ fatcat1111 Entendo isso, mas a maioria das respostas aqui são do tipo "eu também" de expressões regulares pontuais que provavelmente não se encaixam em nenhum dos seus casos de canto. Estes acabam em todos os sites que estou tentando usar e não consigo inserir meu CEP, número de telefone ou endereço de email porque alguém usou uma expressão regular meia-boca (por exemplo: + é um caractere válido nos endereços de email ) As melhores respostas nesta página apontam os usuários para bibliotecas, não para expressões regulares rabiscadas por guardanapos.
Steven Soroka

298
.*

Se os usuários quiserem fornecer seus números de telefone, confie neles para acertar. Se eles não quiserem dar a você, forçá-los a inserir um número válido os enviará ao site de um concorrente ou os fará inserir uma sequência aleatória adequada ao seu regex. Eu posso até ficar tentado a procurar o número de uma linha direta de horóscopo de tarifa premium e inserir isso.

Eu também consideraria uma das seguintes opções como entradas válidas em um site:

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

202
Concordo com o sentimento aqui, mas às vezes é bom executar a validação quando o número de telefone for realmente usado para algo importante no interesse do usuário . O melhor exemplo aqui é a autorização do cartão de crédito para uma compra. Se o número do telefone estiver errado, a autenticação poderá falhar.
Pointy

53
Se o usuário não quiser digitar seu número de telefone, você pode permitir que o campo seja opcional, mas é demais pedir ao usuário que digite um número de telefone válido, caso ele queira digitar um?
Joel McBeth

11
Além disso, um papel da validação é simplesmente lembrar as pessoas de adicionar códigos de área, etc., que eles não se lembrariam de acrescentar, mas que não podem ser adivinhados após o fato.
Ben McIntyre

29
@ Pointy Mas a validação de regex não irá ajudá-lo. A única maneira de validar se o número de telefone está correto é enviar uma mensagem para ele (no caso de celular) E garantir que o usuário confirme usando algum tipo de código de verificação. É isso que você faz quando a correção do número é importante. Tudo o resto é apenas para conveniência do usuário, para proteger contra alguns erros de digitação (mas não todos) e não valida nada.
Alex B

14
Legal. Meu número de telefone é 1 'OU 1 = 1 - PWNED . Veja xkcd.com/327 e owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)
Aaron Newton

171

Eu também sugeriria examinar a Biblioteca do Google " libphonenumber ". Eu sei que não é regex, mas faz exatamente o que você deseja.

Por exemplo, ele reconhecerá que:

15555555555

é um número possível, mas não é um número válido. Ele também suporta países fora dos EUA.

Destaques da funcionalidade:

  • Análise / formatação / validação de números de telefone para todos os países / regiões do mundo.
  • getNumberType- obtém o tipo do número com base no próprio número; capaz de distinguir números de telefone fixo, móvel, gratuito, tarifa premium, custo compartilhado, VoIP e pessoal (sempre que possível).
  • isNumberMatch - obtém um nível de confiança sobre se dois números podem ser iguais.
  • getExampleNumber/ getExampleNumberByType- fornece números de exemplo válidos para todos os países / regiões, com a opção de especificar qual tipo de número de telefone de exemplo é necessário.
  • isPossibleNumber - adivinhar rapidamente se um número é um número de telefone possível usando apenas as informações de comprimento, muito mais rápido que uma validação completa.
  • isValidNumber - validação completa de um número de telefone para uma região usando informações de comprimento e prefixo.
  • AsYouTypeFormatter - formata os números de telefone rapidamente quando os usuários digitam cada dígito.
  • findNumbers - encontra números na entrada de texto.
  • PhoneNumberOfflineGeocoder - fornece informações geográficas relacionadas a um número de telefone.

Exemplos

O maior problema com a validação de número de telefone é que é muito culturalmente dependente.

  • América
    • (408) 974–2042é um número americano válido
    • (999) 974–2042não é um número válido dos EUA
  • Austrália
    • 0404 999 999é um número australiano válido
    • (02) 9999 9999também é um número australiano válido
    • (09) 9999 9999não é um número australiano válido

Uma expressão regular é adequada para verificar o formato de um número de telefone, mas não será capaz de verificar a validade de um número de telefone.

Eu sugeriria pular uma expressão regular simples para testar seu número de telefone e usar uma biblioteca como a do Google libphonenumber(link para o projeto GitHub) .

Apresentando libphonenumber!

Usando um de seus exemplos mais complexos 1-234-567-8901 x1234, você obtém os seguintes dados libphonenumber(link para a demonstração online) :

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

Portanto, você não apenas aprende se o número de telefone é válido (qual é), mas também obtém uma formatação consistente de número de telefone no seu local.

Como bônus, libphonenumberpossui vários conjuntos de dados para verificar a validade dos números de telefone, assim, verificar um número como +61299999999(a versão internacional de (02) 9999 9999) retorna como um número válido com formatação:

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

O libphonenumber também oferece muitos benefícios adicionais, como escolher o local em que o número de telefone foi detectado e também obter as informações de fuso horário no número de telefone:

PhoneNumberOfflineGeocoder Results
Location        Australia

PhoneNumberToTimeZonesMapper Results
Time zone(s)    [Australia/Sydney]

Mas o número de telefone australiano inválido ( (09) 9999 9999) retorna que não é um número de telefone válido.

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     false

A versão do Google possui código para Java e Javascript, mas as pessoas também implementaram bibliotecas para outros idiomas que usam o conjunto de dados de números de telefone do Google i18n:

A menos que você tenha certeza de que sempre aceitará números de um código de idioma e eles sempre estarão em um formato, eu sugiro que não escreva seu próprio código para isso e use libphonenumber para validar e exibir números de telefone.


Observando que há agora também porta Go em: github.com/ttacon/libphonenumber
michaelhanson

Ao verificar se é um número possível, você não precisa especificar um código de país? Estou usando a versão PHP e se eu inserir um número britânico como (substitua 0 por números reais) 07700000000, recebo um Missing or invalid default region.erro. Mas se eu especificar o código do país, ele passará.
BugHunterUK

FYI: Esta biblioteca não suporta alguns países, phpinterviewquestions.co.in/blog/ionic/…
sijo vijayan

1
O @BugHunterUK (e qualquer pessoa que se depare com essa pergunta e se pergunte o mesmo) ao analisar um número, pode especificar a região esperada e a biblioteca procurará números não internacionais nessa região. Se você não especificar, ele rejeitará qualquer coisa que não esteja em um formato internacional válido.
IMSOP

Considere github.com/nyaruka/phonenumbers , pois se tornou o pacote Go "oficial" recomendado pelo Google, em vez da libphonenumber.
DeeZone

78

/^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i

Isso corresponde:

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

Em $ n, ele salva:

  1. Indicador do país
  2. Número de telefone
  3. Extensão

Você pode testá-lo em https://www.regexpal.com/?fam=99127


Este foi o regex mais abrangente que eu já vi. É fácil se locomover até você remover ^e, caso $contrário, eu posso contornar isso usando [111] [111] [1111]ou 111--111--1111e assim por diante . (desculpe, apaguei o meu último comentário)
bafromca

Você pode refazer a frase? Não consigo entender isso: "É fácil obter um arround até você remover ^ e $, ou então eu consigo contornar isso usando [111] [111] [1111]". Isso significa que ele valida '[111] [111] [1111]' quando você pega ^oe o $?
Ismael Miguel

Eu contornei seu regex usando [111] [111] [1111]e 111--111--1111até removê-lo ^e $do regex.
precisa saber é o seguinte

11
^^^ Este é um ótimo exemplo de por que os tópicos de comentários NÃO devem ir ao bate-papo. Estou muito interessado em saber como essa conversa acabou e preciso saber se esse ReGex é resistente o suficiente para usar no meu aplicativo. Infelizmente, a conversa no bate-papo acabou agora.
187148 Matt Cashatt

1
Para ser sincero, eu não fui conversar. Depois de pedir várias vezes explicações, fiquei sem informações. Você sempre pode tentar você mesmo com todos os tipos de números encontrados on-line, em vários formatos. Uma coisa que tentei com este é usar vários números de telefone, mas ele não funciona tão bem se eles têm espaços ao redor. E eu tenho que encontrar uma solução para contar a quantidade de dígitos e aplicar uma quantidade específica.
Ismael Miguel

63

Embora a resposta para remover todo o espaço em branco seja clara, ela realmente não resolve o problema apresentado, que é encontrar um regex. Pegue, por exemplo, meu script de teste que baixa uma página da web e extrai todos os números de telefone usando o regex. Como você precisaria de uma regex de qualquer maneira, é possível que ela faça todo o trabalho. Eu vim com isso:

1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?

Aqui está um script perl para testá-lo. Quando você corresponde, $ 1 contém o código de área, $ 2 e $ 3 contêm o número de telefone e $ 5 contém a extensão. Meu script de teste baixa um arquivo da Internet e imprime todos os números de telefone nele.

#!/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";
        }
}

Editar:

Você pode alterar \ W * para \ s * \ W? \ S * no regex para aumentar um pouco. Eu não estava pensando no regex em termos de, digamos, validar a entrada do usuário em um formulário quando o escrevi, mas essa alteração possibilita o uso do regex para esse fim.

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

2
Para sua informação, o regex também corresponde: o (4570457-6789que seria um erro de digitação bastante comum. Os grupos de jogos também são distorcidos: rubular.com/r/TaTP0mHL5c
SooDesuNe

A pré-adição de @SooDesuNe (^|[^\d\n])(com o sinalizador de múltiplas linhas ativado ) evita o problema geral, garantindo que ele não seja precedido imediatamente por algo numérico.
btown

Observe que isso é centralizado na América do Norte - ele perde "44 7911 123456"
Ben Wheeler

43

Respondi a essa pergunta em outra pergunta do SO antes de decidir incluir também a minha resposta como resposta neste segmento, porque ninguém estava abordando como exigir / não exigir itens, apenas distribuindo regexs: Regex funcionando errado, combinando coisas inesperadas

Na minha publicação no site, criei um guia rápido para ajudar qualquer pessoa a criar sua própria regex para o formato de número de telefone desejado, que eu vou ressaltar (como fiz no outro site) que, se você for muito restritivo, você pode não obter os resultados desejados e não existe uma solução "tamanho único" para aceitar todos os números de telefone possíveis no mundo - apenas o que você decide aceitar como seu formato de escolha. Use por sua conta e risco.

Folha de dicas rápidas

  • Inicie a expressão: /^
  • Se você deseja exigir um espaço, use: [\s]ou\s
  • Se você deseja solicitar parênteses, use: [(]e [)]. Usando \(e\) é feio e pode tornar as coisas confusas.
  • Se você quiser que algo seja opcional, coloque um ? depois
  • Se você quiser um hífen, basta digitar - ou[-] . Porém, se você não o colocar primeiro ou por último em uma série de outros personagens, poderá ser necessário escapá-lo: \-
  • Se você deseja aceitar opções diferentes em um slot, coloque colchetes entre as opções: [-.\s] exigirá um hífen, ponto ou espaço. Um ponto de interrogação após o último colchete tornará todos os opcionais para esse slot.
  • \d{3}: Requer um número de 3 dígitos: 000-999. Taquigrafia para [0-9][0-9][0-9] .
  • [2-9] : Requer um dígito 2-9 para esse slot.
  • (\+|1\s)? : Aceite um "mais" ou um 1 e um espaço (caractere de barra vertical, | , é "ou") e torne-o opcional. O sinal de "mais" deve ser escapado.
  • Se você quiser que números específicos correspondam a um slot, digite-os: [246]exigirá 2, 4 ou 6. [77|78]exigirá 77 ou 78.
  • $/ : Finalize a expressão

1
Isso é muito útil, mas duvido e procure por uma expressão {min, max}. Você pode ajudar?
Ataboy Josef 07/01

Se estamos falando de um único dígito (e você pode fazê-lo corresponder de acordo com isso), veja o [2-9]bloco que coloquei lá. Isso significa que seu mínimo é 2 e seu máximo é 9. Ajuste de acordo.
Vapcguy

30

Eu escrevi mais simples (embora eu não precisei de ponto).

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

Como mencionado abaixo, ele verifica apenas caracteres, não sua estrutura / ordem


38
isso valida toneladas de números que são tecnicamente inválidos. como "- + () () ()) ()))"). Aprenda a ler expressões regulares para entender o que está fazendo.
Steven Soroka 28/03

3
@StevenSoroka tecnicamente ele pode permitir que muitos dos casos inválidos, mas quando pensamos apenas ajudando o usuário a evitar erros comuns com a solução mais simples possível, este é o caminho a percorrer :)
happyhardik

2
isso também corresponde a espaço em branco, linha vazia
Wasim A.

1
@HappyHardik. De fato. Simples e poderoso, para validação básica, deixe o usuário digitar mais de um ponto, traço, colchete ou mais.
585 dijipiji

Apenas usei e está errado em muitos aspectos. Por exemplo, um número de telefone no Reino Unido pode começar com +44 ou um número de telefone pode ter (0) dentro dele. Mas isso não é válido de acordo com sua expressão regular. Eu recomendaria a resposta de @Ismael Miguel. Funciona muito bem e eu recomendo que você revise sua resposta.
Stelios Voskos

22

Se você apenas deseja verificar se não possui lixo aleatório no campo (por exemplo, de spammers de formulários), este regex deve ser bem:

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

Observe que ele não possui regras especiais para quantos dígitos, ou quais números são válidos nesses dígitos, apenas verifica se apenas dígitos, parênteses, traços, mais, espaço, libra, asterisco, ponto, vírgula ou as letras e, x, testão presentes.

Deve ser compatível com números internacionais e formatos de localização. Você prevê alguma necessidade de permitir colchetes quadrados, encaracolados ou angulares para algumas regiões? (atualmente eles não estão incluídos).

Se você deseja manter as regras por dígito (como nos códigos de área e nos prefixos (códigos de câmbio) dos EUA, devem estar entre 200 e 999), boa sorte para você. Manter um conjunto de regras complexo que pode estar desatualizado em qualquer momento no futuro por qualquer país do mundo não parece divertido.

E, embora a exclusão de todos / a maioria dos caracteres não numéricos possa funcionar bem no servidor (especialmente se você estiver planejando passar esses valores para um discador), talvez não queira debater a entrada do usuário durante a validação, principalmente se desejar que eles faça correções em outro campo.


22

Observe que a remoção de ()caracteres não funciona para um estilo comum de escrever números do Reino Unido: o +44 (0) 1234 567890que significa discar para o número internacional
+441234567890
ou para discar para o Reino Unido.01234567890


15

Você já deu uma olhada no RegExLib ?

A inserção do número de telefone nos EUA trouxe de volta uma lista de possibilidades.


3
Essa é uma ótima maneira de integrar bugs obscuros ao seu código.
Tom Lord

12

Minha tentativa de uma regex irrestrita:

/^[+#*\(\)\[\]]*([0-9][ ext+-pw#*\(\)\[\]]*){6,45}$/

Aceita:

+(01) 123 (456) 789 ext555
123456
*44 123-456-789 [321]
123456
123456789012345678901234567890123456789012345
*****++[](][((( 123456tteexxttppww

Rejeita:

mob 07777 777777
1234 567 890 after 5pm
john smith
(empty)
1234567890123456789012345678901234567890123456
911

Cabe a você higienizá-lo para exibição. Depois de validar, pode ser um número.


12

Eu achei que isso funcionava muito bem:

^\(*\+*[1-9]{0,3}\)*-*[1-9]{0,3}[-. /]*\(*[2-9]\d{2}\)*[-. /]*\d{3}[-. /]*\d{4} *e*x*t*\.* *\d{0,4}$

Funciona para estes formatos numéricos:

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

Certifique-se de usar sinalizadores globais e multilinhas para garantir.

Link: http://www.regexr.com/3bp4b


11

Se você estiver falando sobre validação de formulário, a regexp para validar o significado correto e os dados corretos será extremamente complexa devido a diferentes padrões de país e provedor. Também será difícil manter-se atualizado.

Interpreto a pergunta como procurando um padrão amplamente válido, que pode não ser consistente internamente - por exemplo, ter um conjunto de números válido, mas não validar que a linha do tronco, a troca etc. para o padrão válido para o prefixo do código do país .

A América do Norte é direta e, para internacional, prefiro usar um padrão 'idiomático' que cubra as maneiras pelas quais as pessoas especificam e lembram seus números:

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

O padrão norte-americano garante que, se um parêntese estiver incluído, ambos estejam. As contas internacionais de um '+' inicial opcional e o código do país. Depois disso, você está no idioma. Correspondências válidas seriam:

  • (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

Isso pode ser tendencioso, pois minha experiência é limitada à América do Norte, Europa e um pouco da Ásia.


Eu tenho tentado implementar o acima no meu script de validação de javascript, mas continuo recebendo um invalid quantifiererro. Alguma idéia do que estou fazendo de errado?
Jannis

Eu acrescentaria o caso trivial em que o telefone é especificado sem símbolos, mas talvez espaços e códigos de países, na Europa é típico para números locais e móveis: 676412342, 676 46 32 12, 676 463 212
rompe

11

Aqui está um padrão maravilhoso que mais se aproximava da validação que eu precisava alcançar. Não sou o autor original, mas acho que vale a pena compartilhar, pois achei esse problema muito complexo e sem uma resposta concisa ou amplamente útil.

O regex a seguir capturará combinações de números e caracteres amplamente usadas em vários formatos globais de números de telefone:

/^\s*(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/gm

Positivo:
+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

Negativo:
926 3 4
8 800 600-APPLE

Fonte original: http://www.regexr.com/38pvb


Isso tem algum suporte limitado para extensões. Corresponde a "616-555-1234 x567", mas não "616-555-1234 ext. 567".
Jon Schneider

2
Falso positivo para, por exemplo, "------- ((((((55555555" ou "9999999999999999999999999")
mikep:

Ele não valida Nitherland número macdonalds +31 76 596 4192 (eu estava apenas testando para números aleatórios)
BIOHAZARD

10

Meu pressentimento é reforçado pela quantidade de respostas a esse tópico - de que há um número praticamente infinito de soluções para esse problema, nenhuma das quais será elegante.

Honestamente, eu recomendaria que você não tente validar números de telefone. Mesmo se você pudesse escrever um validador grande e cabeludo que permitisse todos os diferentes formatos legítimos, isso acabaria permitindo praticamente qualquer coisa, mesmo remotamente semelhante a um número de telefone.

Na minha opinião, a solução mais elegante é validar um comprimento mínimo, nada mais.


Depois de tentar um número destes e passando os dados existentes e feedback dos usuários i tenderia a concordar ...
Christopher King

Às vezes, você precisa fazer a validação. Se estou enviando códigos de confirmação, não posso simplesmente enviar um código para qualquer lixo aleatório que um remetente de spam tenha inserido no campo. Quero garantir que o número seja provavelmente um número de telefone antes de desperdiçar recursos em enviar mensagens para ele.
Luke

10

Este é um padrão simples de expressão regular para números de telefone celular das Filipinas:

((\+[0-9]{2})|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}

ou

((\+63)|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}

irá corresponder a estes:

+63.917.123.4567  
+63-917-123-4567  
+63 917 123 4567  
+639171234567  
09171234567  

O primeiro corresponderá a QUALQUER código de país com dois dígitos, enquanto o segundo corresponderá exclusivamente ao código de país das Filipinas.

Teste aqui: http://refiddle.com/1ox


Obrigado. Que tal números de telefones fixos com código de área como 028231234? Gostaria de saber se os códigos de área são apenas números de 2 a 3 dígitos e são sempre precedidos por 0?
stormwild

9

Aqui está a minha melhor tentativa até agora. Ele lida com os formatos acima, mas tenho certeza de que estou perdendo outros formatos possíveis.

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

9

Você terá dificuldade em lidar com números internacionais com uma regex única / simples, consulte esta postagem sobre as dificuldades de números de telefone internacionais (e até norte-americanos).

Você deseja analisar os primeiros dígitos para determinar qual é o código do país e agir de maneira diferente com base no país.

Além disso - a lista que você forneceu não inclui outro formato comum dos EUA - deixando de fora o 1. inicial. A maioria dos telefones celulares nos EUA não exige isso, e isso começará a confundir a geração mais jovem, a menos que tenha discado internacionalmente.

Você identificou corretamente que é um problema complicado ...

-Adão


Não é uma solução oferecida. É POSSÍVEL. Só porque é complicado ou complexo, não significa que você deve apenas levantar os braços.
Eric Hodonsky 29/03

7

Depois de ler essas respostas, parece que não havia uma expressão regular direta que possa analisar um monte de texto e obter números de telefone em qualquer formato (incluindo internacionais com e sem o sinal de mais).

Aqui está o que eu usei para um projeto de cliente recentemente, onde tivemos que converter todos os números de telefone em qualquer formato para tel: links.

Até o momento, ele está trabalhando com tudo o que lançou, mas se ocorrerem erros, atualizarei esta resposta.

Regex:

/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/

Função PHP para substituir todos os números de telefone por tel: links (caso alguém esteja curioso):

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

Essa expressão regular corresponde +1 1234562222222222222222222222.
Varda Elentári 13/10/2015

por que não apenas voltar?
precisa saber é o seguinte

Falso positivo para "9999999999999999999999999999999999999"
Ben Wheeler

6

Acredito que o Number :: Phone :: US e Regexp :: Common (particularmente a fonte do Regexp :: Common :: URI :: RFC2806 módulos ) Perl podem ajudar.

A pergunta provavelmente deve ser especificada com mais detalhes para explicar o objetivo de validar os números. Por exemplo, 911 é um número válido nos EUA, mas 911x não é para nenhum valor de x. Isso é para que a companhia telefônica possa calcular quando você terminar de discar. Existem várias variações sobre esse problema. Mas o seu regex não verifica a parte do código de área, o que não parece ser uma preocupação.

Como validar endereços de e-mail, mesmo se você tiver um resultado válido, não poderá saber se ele foi atribuído a alguém até que você o experimente.

Se você está tentando validar a entrada do usuário, por que não normalizar o resultado e terminar com ele? Se o usuário inserir um número que você não pode reconhecer como um número válido, salve-o como inserido ou retire caracteres indisponíveis. O módulo Number :: Phone :: Normalize Perl pode ser uma fonte de inspiração.


Vou falar um pouco sobre isso aqui e dizer que permitir o 911 como número de telefone é provavelmente uma má ideia em quase todas as aplicações desse regex. Boa captura embora.
10132 Nicholas Flynt

4

Eu trabalho para uma empresa de pesquisa de mercado e temos que filtrar esses tipos de informações o tempo todo. Você está complicando demais. Apenas retire os caracteres não alfanuméricos e verifique se há uma extensão.

Para uma análise mais aprofundada, você pode assinar um dos muitos provedores que lhe dará acesso a um banco de dados de números válidos, além de informar se são telefones fixos ou celulares, desconectados etc. Isso custa dinheiro.


Validação? 123% $) *% () $ * () # 456 * () * $ # (* ( # $ @ 8908 iria coincidir com a solução proposta.
PlexQ

1
@PlexQ 555-123-1234, 07777777777, 90210, 01/01/1901 - os usuários são criativos ao compactar lixo por meio da validação. Melhor não marcar quem realmente tem alguns dados estranhos usando validação excessivamente restritiva e dizendo que está errado.
ReactiveRaven

4

Substitua os caracteres de formatação e verifique o restante quanto à validade do telefone. Em PHP,

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

Quebrar uma regexp complexa como essa pode ser igualmente eficaz, mas muito mais simples.


3

Achei isso interessante. Eu não testei, mas parece que funcionaria

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

4
Sua mensagem parece indicar que você não escreveu este código. Você se importaria de citar uma fonte, por favor?
Alastair Irvine


3

Você provavelmente seria melhor usar uma entrada mascarada para isso. Dessa forma, os usuários SÓ podem digitar números e você pode formatar da maneira que achar melhor. Não tenho certeza se isso é para um aplicativo da Web, mas se houver, existe um plugin jQuery com muito clique que oferece algumas opções para fazer isso.

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

Eles ainda abordam como mascarar as entradas de número de telefone em seu tutorial.


3

Aqui está um que funciona bem em JavaScript. Está em uma sequência porque é isso que o widget Dojo estava esperando.

Corresponde a um número NANP da América do Norte de 10 dígitos com ramal opcional. Espaços, traços e pontos são delimitadores aceitos.

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

3

Eu estava lutando com o mesmo problema, tentando tornar minha inscrição à prova do futuro, mas esses caras me levaram na direção certa. Na verdade, não estou checando o número em si para ver se funciona ou não, apenas estou tentando garantir que uma série de números tenha sido inserida com um ramal ou não.

Na pior das hipóteses, se o usuário tivesse que extrair um número não formatado do arquivo XML, ainda assim digitaria os números no teclado numérico do telefone 012345678x5, sem motivo real para mantê-lo bonito. Esse tipo de RegEx sairia algo assim para mim:

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

2

Minha inclinação é concordar que retire sem dígitos e apenas aceite o que há de melhor. Talvez para garantir que pelo menos alguns dígitos estejam presentes, embora isso proíba algo como um número de telefone alfabético "ASK-JAKE", por exemplo.

Algumas expressões perl simples podem ser:

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

Use o primeiro para manter os grupos de dígitos juntos, o que pode fornecer dicas de formatação. Use o segundo para lançar trivialmente todos os que não sejam dígitos.

É preocupante que seja necessário que haja uma pausa e depois mais teclas digitadas? Ou algo como 555-1212 (aguarde o sinal sonoro) 123?


2
    pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$" 
    validateat="onsubmit"

Deve terminar com um dígito, pode começar com (ou + ou um dígito e pode conter + - (ou)


2

Para qualquer pessoa interessada em fazer algo semelhante com os números de celular irlandeses, eis uma maneira simples de realizá-lo:

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

Há também uma solução JQuery nesse link.

EDITAR:

solução 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();
});


});

Fonte .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.