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.
regex
validation
phone-number
Nicholas Trandem
fonte
fonte
555
neles além de911
?Respostas:
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:
Então, quando você exibir, reformate o conteúdo do seu coração. por exemplo
fonte
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:
fonte
/(?:(?:\+?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*\(?([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})
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:
fonte
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:
é 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:
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.
(408) 974–2042
é um número americano válido(999) 974–2042
não é um número válido dos EUA0404 999 999
é um número australiano válido(02) 9999 9999
também é um número australiano válido(09) 9999 9999
não é um número australiano válidoUma 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 dadoslibphonenumber
(link para a demonstração online) :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,
libphonenumber
possui 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: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:
Mas o número de telefone australiano inválido (
(09) 9999 9999
) retorna que não é um número de telefone válido.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.
fonte
07700000000
, recebo umMissing or invalid default region.
erro. Mas se eu especificar o código do país, ele passará./^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i
Isso corresponde:
Em $ n, ele salva:
Você pode testá-lo em https://www.regexpal.com/?fam=99127
fonte
^
e, caso$
contrário, eu posso contornar isso usando[111] [111] [1111]
ou111--111--1111
e assim por diante . (desculpe, apaguei o meu último comentário)^
oe o$
?[111] [111] [1111]
e111--111--1111
até removê-lo^
e$
do regex.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:
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.
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.
fonte
(4570457-6789
que seria um erro de digitação bastante comum. Os grupos de jogos também são distorcidos: rubular.com/r/TaTP0mHL5c(^|[^\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.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
/^
[\s]
ou\s
[(]
e[)]
. Usando\(
e\)
é feio e pode tornar as coisas confusas.?
depois-
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:\-
[-.\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.[246]
exigirá 2, 4 ou 6.[77|78]
exigirá 77 ou 78.$/
: Finalize a expressãofonte
[2-9]
bloco que coloquei lá. Isso significa que seu mínimo é 2 e seu máximo é 9. Ajuste de acordo.Eu escrevi mais simples (embora eu não precisei de ponto).
Como mencionado abaixo, ele verifica apenas caracteres, não sua estrutura / ordem
fonte
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:
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
,t
estã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.
fonte
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 567890
que significa discar para o número internacional+441234567890
ou para discar para o Reino Unido.
01234567890
fonte
Você já deu uma olhada no RegExLib ?
A inserção do número de telefone nos EUA trouxe de volta uma lista de possibilidades.
fonte
Minha tentativa de uma regex irrestrita:
Aceita:
Rejeita:
Cabe a você higienizá-lo para exibição. Depois de validar, pode ser um número.
fonte
Eu achei que isso funcionava muito bem:
Funciona para estes formatos numéricos:
Certifique-se de usar sinalizadores globais e multilinhas para garantir.
Link: http://www.regexr.com/3bp4b
fonte
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:
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.
fonte
invalid quantifier
erro. Alguma idéia do que estou fazendo de errado?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
fonte
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.
fonte
Este é um padrão simples de expressão regular para números de telefone celular das Filipinas:
ou
irá corresponder a estes:
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
fonte
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.
fonte
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
fonte
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):
fonte
+1 1234562222222222222222222222
.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.
fonte
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.
fonte
Substitua os caracteres de formatação e verifique o restante quanto à validade do telefone. Em PHP,
Quebrar uma regexp complexa como essa pode ser igualmente eficaz, mas muito mais simples.
fonte
Achei isso interessante. Eu não testei, mas parece que funcionaria
fonte
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.
fonte
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.
fonte
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:01234467 extension 123456
01234567x123456
01234567890
fonte
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:
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?
fonte
Deve terminar com um dígito, pode começar com (ou + ou um dígito e pode conter + - (ou)
fonte
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
Há também uma solução JQuery nesse link.
EDITAR:
solução jQuery:
Fonte .
fonte