Expressão regular para reformatar um número de telefone dos EUA em Javascript

101

Estou tentando reformatar (substituir, não validar - há muitas referências para validação) um número de telefone para exibição em Javascript. Aqui está um exemplo de alguns dos dados:

  • 123 4567890
  • (123) 456-7890
  • (123)456-7890
  • 123 456 7890
  • 123.456.7890
  • (em branco / nulo)
  • 1234567890

Existe uma maneira fácil de usar uma expressão regular para fazer isso? Estou procurando a melhor maneira de fazer isso. Existe uma maneira melhor?

Quero reformatar o número para o seguinte: (123) 456-7890

Matt K
fonte
3
E qual deles é o seu formato de destino?
Até Helge
Este aqui: (123) 456-7890
Matt K
3
Eu diria que basta retirar todos os caracteres não-dígitos e, em seguida, pegar três substrings.
Wiseguy
2
@Wiseguy por favor poste isso como uma resposta (com um exemplo), já que isso é realmente o que o OP deve fazer.
Brian Driscoll
1
Você também precisa especificar como cada um dos formatos aceitos mapeia para o formato de destino, o que não é óbvio se a entrada for nula. A menos que você esteja disposto a usar uma condição extra para eliminar esse caso.
Jon

Respostas:

248

Supondo que você deseja o formato " (123) 456-7890":

function formatPhoneNumber(phoneNumberString) {
  var cleaned = ('' + phoneNumberString).replace(/\D/g, '')
  var match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/)
  if (match) {
    return '(' + match[1] + ') ' + match[2] + '-' + match[3]
  }
  return null
}

Esta é uma versão que permite o +1código internacional opcional :

function formatPhoneNumber(phoneNumberString) {
  var cleaned = ('' + phoneNumberString).replace(/\D/g, '')
  var match = cleaned.match(/^(1|)?(\d{3})(\d{3})(\d{4})$/)
  if (match) {
    var intlCode = (match[1] ? '+1 ' : '')
    return [intlCode, '(', match[2], ') ', match[3], '-', match[4]].join('')
  }
  return null
}
formatPhoneNumber('+12345678900') // => "+1 (234) 567-8900"
formatPhoneNumber('2345678900')   // => "(234) 567-8900"
matemática
fonte
2
Perfeito; obrigado! No entanto, mudei return (!m) ? nullpara return (!m) ? ""depois de adicionar esta função.
Matt K
2
Uma boa lição sobre como abordar um problema. Eu estava tentando pensar em como combinar todos os casos possíveis - você elimina o irrelevante e vê se há uma correspondência. Muito agradável.
Jkleg de
2
FYI isso não funciona para números como + 1555-555-5555
Will
'' + phoneNumberStringé o mesmo que phoneNumberString... Já é uma string.
YungGun
@YungGun, a menos que alguém chame a função com um número, por exemploformatPhoneNumber(8001231234)
maerics
32

Solução possível:

function normalize(phone) {
    //normalize string and remove all unnecessary characters
    phone = phone.replace(/[^\d]/g, "");

    //check if number length equals to 10
    if (phone.length == 10) {
        //reformat and return phone number
        return phone.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");
    }

    return null;
}

var phone = '(123)4567890';
phone = normalize(phone); //(123) 456-7890
ioseb
fonte
27

var x = '301.474.4062';
    
x = x.replace(/\D+/g, '')
     .replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');

alert(x);

Sean Bright
fonte
1
Obrigado Sean, gostei da sua solução inline simples e curta.
user752746
1
Obrigado por isso! Eu mudei x = x.replace(/[^\d]+/g, '') .replace(/(\d{1})(\d{3})(\d{3})(\d{4})/, '+$1 ($2) $3-$4');para funcionar para adicionar '+1' na frente do número de telefone, por exemplo
Greg A
Obrigado! isso é tudo que eu precisava
Albert Hidalgo
8

Esta resposta é emprestada da resposta da matemática. Ele difere principalmente porque aceita números de telefone parcialmente inseridos e formata as partes que foram inseridas.

phone = value.replace(/\D/g, '');
const match = phone.match(/^(\d{1,3})(\d{0,3})(\d{0,4})$/);
if (match) {
  phone = `${match[1]}${match[2] ? ' ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}`;
}
return phone
David Baucum
fonte
Isso funciona conforme você digita, adicionando o formato desejado do pôster de origem. Após 1,5 horas de pesquisa, estou feliz por ter tentado este!
fungusanthrax
Eu adicionei parênteses ao redor do código de área, se isso ajudar:(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}
Peter Hollingsworth,
Na verdade, o problema é que você não pode retroceder sobre o '-' ou o espaço do meio da corda. Você precisa evitar a reformatação quando o usuário está retrocedendo (por exemplo, newstring.length < oldstring.lengthOU para rastrear a posição do cursor e descobrir quando o usuário acabou de retroceder sobre esses delimitadores, por exemploif (cursorPosition === 4 && numericString.length > 3)
Peter Hollingsworth,
No meu código de reação, eu consigo contornar isso armazenando internamente apenas o número inserido e, em seguida, formatar o que é colocado no campo. Portanto, o backspace remove o caractere anterior no valor real, não o valor exibido.
David Baucum,
7

Estou usando esta função para formatar números dos EUA.

function formatUsPhone(phone) {

    var phoneTest = new RegExp(/^((\+1)|1)? ?\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})( ?(ext\.? ?|x)(\d*))?$/);

    phone = phone.trim();
    var results = phoneTest.exec(phone);
    if (results !== null && results.length > 8) {

        return "(" + results[3] + ") " + results[4] + "-" + results[5] + (typeof results[8] !== "undefined" ? " x" + results[8] : "");

    }
    else {
         return phone;
    }
}

Aceita quase todas as formas imagináveis ​​de escrever um número de telefone nos Estados Unidos. O resultado é formatado em um formato padrão de (987) 654-3210 x123

Mikryz
fonte
3

pensando para trás

Pegue os últimos dígitos apenas (até 10), ignorando o primeiro "1".

function formatUSNumber(entry = '') {
  const match = entry
    .replace(/\D+/g, '').replace(/^1/, '')
    .match(/([^\d]*\d[^\d]*){1,10}$/)[0]
  const part1 = match.length > 2 ? `(${match.substring(0,3)})` : match
  const part2 = match.length > 3 ? ` ${match.substring(3, 6)}` : ''
  const part3 = match.length > 6 ? `-${match.substring(6, 10)}` : ''    
  return `${part1}${part2}${part3}`
}

exemplo de entrada / saída conforme você digita

formatUSNumber('+1333')
// (333)

formatUSNumber('333')
// (333)

formatUSNumber('333444')
// (333) 444

formatUSNumber('3334445555')
// (333) 444-5555
Jason Sebring
fonte
2

Eu tenho estendido a resposta de David Baucum para incluir suporte para extensões de até 4 dígitos de comprimento. Também inclui os parênteses solicitados na pergunta original. Essa formatação funcionará conforme você digita no campo.

phone = phone.replace(/\D/g, '');
const match = phone.match(/^(\d{1,3})(\d{0,3})(\d{0,4})(\d{0,4})$/);
if (match) {
    phone = `(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}${match[4] ? ' x' : ''}${match[4]}`;
}
return phone;
Jeremy
fonte
1
var numbers = "(123) 456-7890".replace(/[^\d]/g, ""); //This strips all characters that aren't digits
if (numbers.length != 10) //wrong format
    //handle error
var phone = "(" + numbers.substr(0, 3) + ") " + numbers.substr(3, 3) + "-" + numbers.substr(6); //Create format with substrings
Alex Turpin
fonte
1

Quase todos eles apresentam problemas quando o usuário tenta retroceder nos delimitadores, especialmente no meio da string.

Esta é uma solução jquery que lida com isso e também garante que o cursor fique no lugar certo enquanto você edita:

//format text input as phone number (nnn) nnn-nnnn
$('.myPhoneField').on('input', function (e){
    var $phoneField = e.target;
    var cursorPosition = $phoneField.selectionStart;
    var numericString = $phoneField.value.replace(/\D/g, '').substring(0, 10);

    // let user backspace over the '-'
    if (cursorPosition === 9 && numericString.length > 6) return;

    // let user backspace over the ') '
    if (cursorPosition === 5 && numericString.length > 3) return;
    if (cursorPosition === 4 && numericString.length > 3) return;

    var match = numericString.match(/^(\d{1,3})(\d{0,3})(\d{0,4})$/);
    if (match) {
        var newVal = '(' + match[1];
        newVal += match[2] ? ') ' + match[2] : '';
        newVal += match[3] ? '-' + match[3] : '';

        // to help us put the cursor back in the right place
        var delta = newVal.length - Math.min($phoneField.value.length, 14);      
        $phoneField.value = newVal;
        $phoneField.selectionEnd = cursorPosition + delta;
    } else {
        $phoneField.value = '';        
    }
})
Peter Hollingsworth
fonte
0

Aqui está um que aceita números de telefone e números de telefone com ramais.

function phoneNumber(tel) {
var toString = String(tel),
    phoneNumber = toString.replace(/[^0-9]/g, ""),
    countArrayStr = phoneNumber.split(""),
    numberVar = countArrayStr.length,
    closeStr = countArrayStr.join("");
if (numberVar == 10) {
    var phone = closeStr.replace(/(\d{3})(\d{3})(\d{4})/, "$1.$2.$3"); // Change number symbols here for numbers 10 digits in length. Just change the periods to what ever is needed.
} else if (numberVar > 10) {
    var howMany = closeStr.length,
        subtract = (10 - howMany),
        phoneBeginning = closeStr.slice(0, subtract),
        phoneExtention = closeStr.slice(subtract),
        disX = "x", // Change the extension symbol here
        phoneBeginningReplace = phoneBeginning.replace(/(\d{3})(\d{3})(\d{4})/, "$1.$2.$3"), // Change number symbols here for numbers greater than 10 digits in length. Just change the periods and to what ever is needed. 
        array = [phoneBeginningReplace, disX, phoneExtention],
        afterarray = array.splice(1, 0, " "),
        phone = array.join("");

} else {
    var phone = "invalid number US number";
}
return phone;
}

phoneNumber("1234567891"); // Your phone number here
jjones
fonte
0

Você pode usar essas funções para verificar números de telefone válidos e normalizá-los:

let formatPhone = (dirtyNumber) => {
 return dirtyNumber.replace(/\D+/g, '').replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}

let isPhone = (phone) => {
   //normalize string and remove all unnecessary characters
   phone = phone.replace(/\D+/g, '');
   return phone.length == 10? true : false;
}
Rodnier Borrego Clavero
fonte
0

As soluções acima são superiores, especialmente se estiver usando Java e encontrando mais números com mais de 10 dígitos, como prefixo de código internacional ou números de ramais adicionais. Esta solução é básica (sou um iniciante no mundo regex) e foi projetada com números de telefone dos EUA em mente e só é útil para strings com apenas 10 números com talvez alguns caracteres de formatação, ou talvez nenhum caractere de formatação (apenas 10 números ) Como tal, recomendo esta solução apenas para aplicações semi-automáticas. Pessoalmente, prefiro armazenar números como apenas 10 números sem formatar caracteres, mas também quero ser capaz de converter ou limpar números de telefone para o formato padrão que as pessoas normais e os aplicativos / telefones reconhecerão instantaneamente à vontade.

Encontrei este post procurando por algo que eu pudesse usar com um aplicativo de limpeza de texto que tenha recursos PCRE Regex (mas sem funções java). Vou postar isso aqui para pessoas que poderiam usar uma solução Regex pura e simples que poderia funcionar em uma variedade de editores de texto, limpadores, expansores ou mesmo alguns gerenciadores de área de transferência. Eu pessoalmente uso Sublime e TextSoap. Esta solução foi feita para Text Soap, uma vez que está na barra de menus e fornece um menu suspenso onde você pode acionar ações de manipulação de texto no que é selecionado pelo cursor ou no que está na área de transferência.

Minha abordagem consiste essencialmente em substituir / pesquisar e substituir regexes. Cada pesquisa de substituição e substituição envolve duas regexes, uma para pesquisa e outra para substituição.

Substituição / Pesquisa e Substituição # 1

  • A primeira substituição / pesquisa e substituição remove os números não numéricos de um número de 10 dígitos para uma sequência de 10 dígitos.

Primeira substituição / pesquisa Regex:\D

  • Esta string de pesquisa corresponde a todos os caracteres que não sejam um dígito.

Primeira substituição / substituir Regex: "" (nada, nem mesmo um espaço)

  • Deixe o campo substituto completamente em branco, nenhum espaço em branco deve existir, incluindo espaços. Isso resultará na exclusão de todos os caracteres não-dígitos correspondentes. Você deve ter entrado com 10 dígitos + caracteres de formatação antes desta operação e sair com 10 dígitos sem caracteres de formatação.

Substituição / Pesquisa e Substituição # 2

  • A segunda substituição / procura e parte de procura de substituição da operação captura grupos para código de área $1, um grupo de captura para o segundo conjunto de três números $2e o último grupo de captura para o último conjunto de quatro números $3. A regex para a parte substituta da operação insere a formatação de número de telefone dos EUA entre o grupo de dígitos capturados.

Segunda Substituição / Pesquisa Regex:(\d{3})(\d{3})(\d{4})

Segunda Substituição / Substituir Regex:\($1\) $2\-$3

  • A barra invertida \escapa os caracteres especiais (, ), (<-whitespace), e -uma vez que estamos inserindo-os entre os nossos números capturados em grupos de captura $1, $2, e $3para fins do número de telefone de formatação.

  • No TextSoap, criei um limpador personalizado que inclui as duas ações da operação de substituição, portanto, na prática, parece idêntico à execução de um script. Tenho certeza de que essa solução poderia ser melhorada, mas espero que a complexidade aumente um pouco. Uma versão aprimorada desta solução é bem-vinda como uma experiência de aprendizado, se alguém quiser adicionar a isso.

adamlogan
fonte
-2

Para números de telefone dos EUA

/^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/

Vamos dividir essa expressão regular em fragmentos menores para torná-la fácil de entender.

  • /^\(?: Significa que o número de telefone pode começar com um opcional (.
  • (\d{3}): Após o opcional (, deve haver 3 dígitos numéricos. Se o número de telefone não tiver um (, ele deve começar com 3 dígitos. Por exemplo, (308ou 308.
  • \)?: Significa que o número de telefone pode ter um opcional )após os 3 primeiros dígitos.
  • [- ]?: Em seguida, o número de telefone pode ter um hífen opcional ( -) após )se presente ou após os 3 primeiros dígitos.
  • (\d{3}): Então, deve haver mais 3 dígitos numéricos. Por exemplo (308)-135ou 308-135ou308135
  • [- ]?: Após o segundo conjunto de 3 dígitos, o número de telefone pode ter outro hífen opcional ( -). Por exemplo (308)-135-ou 308-135-ou308135-
  • (\d{4})$/: Finalmente, o número de telefone deve terminar com quatro dígitos. Por exemplo, (308)-135-7895ou 308-135-7895ou 308135-7895ou3081357895 .

    Referência:

http://www.zparacha.com/phone_number_regex/

Bebu
fonte
1
Copiar coisas de outros sites e nem mesmo postar o link é um comportamento muito ruim: zparacha.com/phone_number_regex
Até Helge
1
Sinto muito, não tinha ideia de que tínhamos que postar o link. Achei que devíamos apenas fornecer respostas às perguntas postadas.
Bebu
5
Nunca é normal fazer com que o trabalho de outra pessoa se pareça com o seu. Para a próxima vez, lembre-se de que não há nada de errado em postar links, mas copiar (especialmente sem fornecer um link) não é. E você sempre tem a opção de editar sua resposta.
Até Helge
Votos negados porque o autor não respondeu como substituir o número de telefone conforme solicitado pelo autor.
BrianHVB