Expression régulière pour reformater un numéro de téléphone américain en Javascript

97

Je cherche à reformater (remplacer, non valider - il existe de nombreuses références pour valider) un numéro de téléphone à afficher en Javascript. Voici un exemple de certaines des données:

  • 123 4567890
  • (123) 456-7890
  • (123)456-7890
  • 123 456 7890
  • 123.456.7890
  • (vide / nul)
  • 1234567890

Existe-t-il un moyen simple d'utiliser une expression régulière pour ce faire? Je cherche la meilleure façon de faire cela. Y a-t-il un meilleur moyen?

Je souhaite reformater le numéro comme suit: (123) 456-7890

Matt K
la source
3
Et lequel de ceux-ci est votre format cible?
Till Helge
Celui-ci: (123) 456-7890
Matt K
3
Je dirais simplement supprimer tous les caractères non numériques, puis prendre trois sous-chaînes.
Wiseguy
2
@Wiseguy s'il vous plaît postez cela comme une réponse (avec un exemple), car c'est vraiment ce que OP devrait faire.
Brian Driscoll
1
Vous devez également spécifier comment chacun des formats acceptés correspond au format cible, ce qui n'est pas du tout évident si l'entrée est nulle. À moins que vous ne souhaitiez utiliser une condition supplémentaire pour éliminer ce cas.
Jon

Réponses:

240

En supposant que vous vouliez le format " (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
}

Voici une version qui autorise le +1code international facultatif :

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"
maerics
la source
2
Parfait; Merci! Cependant, j'ai changé return (!m) ? nullaprès return (!m) ? ""avoir ajouté cette fonction.
Matt K
2
Une belle leçon pour aborder un problème. J'essayais de réfléchir à la façon de faire correspondre tous les cas possibles - vous éliminez le non pertinent et voyez s'il y a correspondance. Très agréable.
Jkleg
2
Pour info, cela ne fonctionne pas pour des numéros comme + 1555-555-5555
Will
'' + phoneNumberStringest le même que phoneNumberString... C'est déjà une chaîne.
YungGun
@YungGun à moins que quelqu'un appelle la fonction avec un numéro, par exempleformatPhoneNumber(8001231234)
maerics
32

Solution possible:

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
la source
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
la source
1
Merci Sean, j'aime votre courte solution en ligne simple.
user752746
1
Merci pour cela! Je l'ai changé x = x.replace(/[^\d]+/g, '') .replace(/(\d{1})(\d{3})(\d{3})(\d{4})/, '+$1 ($2) $3-$4');pour travailler pour ajouter «+1» devant le numéro de téléphone par exemple
Greg A
Merci! c'est juste dont j'avais besoin
Albert Hidalgo
8

Cette réponse emprunte à la réponse des maerics. Il diffère principalement en ce qu'il accepte les numéros de téléphone partiellement saisis et formate les parties qui ont été saisies.

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
la source
Cela fonctionne au fur et à mesure que vous tapez, en ajoutant le format souhaité à partir de l'affiche source. Après 1,5 heure de recherche, je suis content d'avoir essayé celui-ci!
fungusanthrax
J'ai ajouté des parenthèses autour de l'indicatif régional si cela aide:(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}
Peter Hollingsworth le
En fait, le problème est que vous ne pouvez pas revenir en arrière sur le «-» ou l'espace à partir du milieu de la chaîne. Vous devez empêcher le reformatage lorsque l'utilisateur effectue un retour arrière (par exemple, newstring.length < oldstring.lengthOU pour suivre la position du curseur et déterminer quand l'utilisateur vient de revenir en arrière sur ces délimiteurs, par exempleif (cursorPosition === 4 && numericString.length > 3)
Peter Hollingsworth
Dans mon code de réaction, je contourne ce problème en ne stockant en interne que le nombre entré, puis en formatant ce qui est placé dans le champ. Ainsi, le retour arrière supprime le caractère précédent de la valeur réelle, pas la valeur affichée.
David Baucum le
5

J'utilise cette fonction pour formater les nombres américains.

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

Il accepte presque toutes les manières imaginables d'écrire un numéro de téléphone américain. Le résultat est formaté dans une forme standard de (987) 654-3210 x123

Mikryz
la source
3

penser à l'envers

Ne prenez que les derniers chiffres (jusqu'à 10) en ignorant le premier "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}`
}

exemple d'entrée / sortie à mesure que vous tapez

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

formatUSNumber('333')
// (333)

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

formatUSNumber('3334445555')
// (333) 444-5555
Jason Sebring
la source
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
la source
0

En voici un qui acceptera à la fois les numéros de téléphone et les numéros de téléphone avec des extensions.

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
la source
0

Vous pouvez utiliser ces fonctions pour vérifier les numéros de téléphone valides et les normaliser:

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
la source
0

J'ai étendu la réponse de David Baucum pour inclure la prise en charge des extensions jusqu'à 4 chiffres. Il comprend également les parenthèses demandées dans la question initiale. Cette mise en forme fonctionnera lorsque vous tapez dans le champ.

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;
Jérémie
la source
0

Presque tous ont des problèmes lorsque l'utilisateur essaie de revenir en arrière sur les délimiteurs, en particulier à partir du milieu de la chaîne.

Voici une solution jquery qui gère cela et s'assure également que le curseur reste au bon endroit lorsque vous modifiez:

//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
la source
0

Les solutions ci-dessus sont supérieures, en particulier si vous utilisez Java, et rencontrez plus de numéros avec plus de 10 chiffres tels que le préfixe de code international ou des numéros d'extension supplémentaires. Cette solution est basique (je suis un débutant dans le monde des regex) et conçue avec les numéros de téléphone américains à l'esprit et n'est utile que pour les chaînes avec seulement 10 chiffres avec peut-être quelques caractères de formatage, ou peut-être pas de caractères de formatage du tout (juste 10 chiffres ). En tant que tel, je recommanderais cette solution uniquement pour les applications semi-automatiques. Personnellement, je préfère stocker les numéros sous forme de seulement 10 numéros sans caractères de formatage, mais je souhaite également pouvoir convertir ou nettoyer les numéros de téléphone au format standard que les personnes normales et les applications / téléphones reconnaîtront instantanément à volonté.

Je suis tombé sur cet article à la recherche de quelque chose que je pourrais utiliser avec une application de nettoyage de texte dotée de capacités PCRE Regex (mais pas de fonctions java). Je publierai ceci ici pour les personnes qui pourraient utiliser une solution Regex pure et simple qui pourrait fonctionner dans une variété d'éditeurs de texte, de nettoyeurs, d'extensions ou même de gestionnaires de presse-papiers. J'utilise personnellement Sublime et TextSoap. Cette solution a été conçue pour Text Soap car elle se trouve dans la barre de menus et fournit un menu déroulant où vous pouvez déclencher des actions de manipulation de texte sur ce qui est sélectionné par le curseur ou sur ce qui se trouve dans le presse-papiers.

Mon approche est essentiellement deux substitution / recherche et remplacement des expressions régulières. Chaque recherche de substitution et remplacement implique deux expressions régulières, une pour la recherche et une pour remplacer.

Substitution / Rechercher et remplacer # 1

  • La première substitution / recherche et remplacement supprime les nombres non numériques d'un nombre à 10 chiffres autrement en une chaîne de 10 chiffres.

Première substitution / expression régulière de recherche :\D

  • Cette chaîne de recherche correspond à tous les caractères qui ne sont pas un chiffre.

First Substitution / Replace Regex: "" (rien, pas même un espace)

  • Laissez le champ de remplacement complètement vide, aucun espace blanc ne doit exister, y compris les espaces. Cela entraînera la suppression de tous les caractères non numériques correspondants. Vous devriez avoir entré avec 10 chiffres + caractères de formatage avant cette opération et sortir avec 10 chiffres sans caractères de formatage.

Substitution / Rechercher et remplacer # 2

  • La seconde substitution / rechercher et remplacer recherche une partie des groupes de captures d'exploitation pour l' indicatif régional $1, un groupe de capture pour la deuxième série de trois chiffres $2, et le dernier groupe de capture pour la dernière série de quatre numéros $3. L'expression régulière de la partie de substitution de l'opération insère le formatage du numéro de téléphone américain entre le groupe de chiffres capturé.

Deuxième substitution / expression régulière de recherche :(\d{3})(\d{3})(\d{4})

Second Substitution / Replace Regex:\($1\) $2\-$3

  • La barre oblique inverse \échappe aux caractères spéciaux (, ), (<-whitespace), et -puisque nous les insérer entre nos chiffres capturés dans des groupes de capture $1, $2, et $3pour le numéro de téléphone aux États - Unis des fins de mise.

  • Dans TextSoap, j'ai créé un nettoyeur personnalisé qui inclut les deux actions d'opération de substitution, donc en pratique, cela semble identique à l'exécution d'un script. Je suis sûr que cette solution pourrait être améliorée mais je m'attends à ce que la complexité augmente un peu. Une version améliorée de cette solution est accueillie comme une expérience d'apprentissage si quelqu'un souhaite ajouter à cela.

adamlogan
la source
-2

Pour les numéros de téléphone américains

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

Divisons cette expression régulière en fragments plus petits pour que cela soit facile à comprendre.

  • /^\(?: Signifie que le numéro de téléphone peut commencer par une option (.
  • (\d{3}): Après l'option, (il doit y avoir 3 chiffres numériques. Si le numéro de téléphone n'a pas de (, il doit commencer par 3 chiffres. Par exemple (308ou 308.
  • \)?: Signifie que le numéro de téléphone peut avoir une option )après les 3 premiers chiffres.
  • [- ]?: Ensuite, le numéro de téléphone peut avoir un tiret optionnel ( -) après )s'il est présent ou après les 3 premiers chiffres.
  • (\d{3}): Ensuite, il doit y avoir 3 chiffres numériques supplémentaires. Par exemple (308)-135ou 308-135ou308135
  • [- ]?: Après le deuxième ensemble de 3 chiffres, le numéro de téléphone peut avoir un autre tiret facultatif ( -). Par exemple (308)-135-ou 308-135-ou308135-
  • (\d{4})$/: Enfin, le numéro de téléphone doit se terminer par quatre chiffres. Par exemple, (308)-135-7895ou 308-135-7895ou 308135-7895ou 3081357895.

    Référence :

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

Bebu
la source
1
Copier des éléments d'autres sites Web et ne même pas publier le lien est un très mauvais comportement: zparacha.com/phone_number_regex
Till Helge
1
Je suis désolé, je ne savais pas que nous devions publier un lien. J'ai pensé que nous devions simplement fournir des réponses aux questions posées.
Bebu
5
Il n'est jamais acceptable de faire en sorte qu'un autre travail ressemble au vôtre. N'oubliez pas pour la prochaine fois qu'il n'y a rien de mal à publier des liens, mais la copie (surtout sans fournir de lien) ne l'est pas. Et vous avez toujours la possibilité de modifier votre réponse.
Till Helge
Évalué parce que l'auteur n'a pas répondu comment remplacer le numéro de téléphone comme l'auteur l'a demandé.
BrianHVB