Expresión regular para reformatear un número de teléfono de EE. UU. En Javascript

97

Estoy buscando reformatear (reemplazar, no validar; hay muchas referencias para validar) un número de teléfono para mostrarlo en Javascript. A continuación, se muestra un ejemplo de algunos de los datos:

  • 123 4567890
  • (123) 456-7890
  • (123)456-7890
  • 123 456 7890
  • 123.456.7890
  • (en blanco / nulo)
  • 1234567890

¿Existe una forma sencilla de utilizar una expresión regular para hacer esto? Estoy buscando la mejor manera de hacer esto. ¿Existe una forma mejor?

Quiero reformatear el número a lo siguiente: (123) 456-7890

Matt K
fuente
3
¿Y cuál de esos es su formato de destino?
Hasta Helge
Éste: (123) 456-7890
Matt K
3
Yo diría que elimine todos los caracteres que no sean dígitos y luego tome tres subcadenas.
Wiseguy
2
@Wiseguy, publique eso como respuesta (con un ejemplo), ya que eso es realmente lo que OP debería hacer.
Brian Driscoll
1
También debe especificar cómo se asigna cada uno de los formatos aceptados al formato de destino, lo cual no es obvio en absoluto si la entrada es nula. A menos que esté dispuesto a usar un condicional adicional para eliminar ese caso.
Jon

Respuestas:

240

Suponiendo que desea el 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
}

Aquí hay una versión que permite el +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"
maerics
fuente
2
Perfecto; ¡gracias! Sin embargo, cambié return (!m) ? nulla return (!m) ? ""después de agregar esta función.
Matt K
2
Una buena lección sobre cómo abordar un problema. Estaba tratando de pensar cómo hacer coincidir todos los casos posibles: eliminas lo irrelevante y ves si hay una coincidencia. Muy agradable.
Jkleg
2
Para su información, esto no funciona para números como + 1555-555-5555
será
'' + phoneNumberStringes lo mismo que phoneNumberString... Ya es una cadena.
YungGun
@YungGun a menos que alguien llame a la función con un número, por ejemploformatPhoneNumber(8001231234)
maerics
32

Solución posible:

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
fuente
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
fuente
1
Gracias Sean, me gusta tu solución en línea simple y corta.
user752746
1
¡Gracias por esto! Lo cambié para x = x.replace(/[^\d]+/g, '') .replace(/(\d{1})(\d{3})(\d{3})(\d{4})/, '+$1 ($2) $3-$4');que funcione para agregar '+1' delante del número de teléfono, por ejemplo
Greg A
¡Gracias! esto es solo lo que necesitaba
Albert Hidalgo
8

Esta respuesta toma prestada de la respuesta de maerics. Se diferencia principalmente en que acepta números de teléfono ingresados ​​parcialmente y formatea las partes ingresadas.

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
fuente
Esto funciona a medida que escribe, agregando el formato deseado del póster de origen. Después de 1,5 horas de búsqueda, ¡estoy feliz de haber probado este!
hongoantrax
Agregué paréntesis alrededor del código de área si eso ayuda:(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}
Peter Hollingsworth
En realidad, el problema es que no puede retroceder sobre el '-' o el espacio desde la mitad de la cadena. Debe evitar volver a formatear cuando el usuario está retrocediendo (por ejemplo, newstring.length < oldstring.lengthO para rastrear la posición del cursor y averiguar cuándo el usuario acaba de retroceder sobre esos delimitadores, por ejemploif (cursorPosition === 4 && numericString.length > 3)
Peter Hollingsworth
En mi código de reacción, soluciono esto almacenando internamente solo el número ingresado y luego formateando lo que se coloca en el campo. Entonces, el retroceso elimina el carácter anterior en el valor real, no el valor mostrado.
David Baucum
5

Estoy usando esta función para formatear números de EE. UU.

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

Acepta casi todas las formas imaginables de escribir un número de teléfono de EE. UU. El resultado tiene el formato estándar de (987) 654-3210 x123

mikryz
fuente
3

pensando al revés

Tome solo los últimos dígitos (hasta 10) ignorando el primer "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}`
}

ejemplo de entrada / salida a medida que escribe

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

formatUSNumber('333')
// (333)

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

formatUSNumber('3334445555')
// (333) 444-5555
Jason Sebring
fuente
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
fuente
1

Casi todos estos tienen problemas cuando el usuario intenta retroceder sobre los delimitadores, particularmente desde la mitad de la cadena.

Aquí hay una solución de jquery que maneja eso y también se asegura de que el cursor permanezca en el lugar correcto mientras 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
fuente
0

Aquí hay uno que acepta tanto números de teléfono como números de teléfono con extensiones.

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
fuente
0

Puede usar estas funciones para verificar números de teléfono válidos y normalizarlos:

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
fuente
0

Hemos ampliado en la respuesta de David Baucum para incluir soporte para extensiones de hasta 4 dígitos de longitud. También incluye los paréntesis solicitados en la pregunta original. Este formato funcionará mientras escribe en el 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
fuente
0

Las soluciones anteriores son superiores, especialmente si utiliza Java y encuentra más números con más de 10 dígitos, como el prefijo del código internacional o números de extensión adicionales. Esta solución es básica (soy un principiante en el mundo de las expresiones regulares) y está diseñada teniendo en cuenta los números de teléfono de EE. UU. Y solo es útil para cadenas con solo 10 números con quizás algunos caracteres de formato, o tal vez sin caracteres de formato (solo 10 números ). Como tal, recomendaría esta solución solo para aplicaciones semiautomáticas. Personalmente, prefiero almacenar números como solo 10 números sin formatear caracteres, pero también quiero poder convertir o limpiar números de teléfono al formato estándar que la gente normal y las aplicaciones / teléfonos reconocerán instantáneamente a voluntad.

Encontré esta publicación buscando algo que pudiera usar con una aplicación de limpieza de texto que tenga capacidades PCRE Regex (pero no funciones de Java). Publicaré esto aquí para las personas que podrían usar una solución Regex pura simple que podría funcionar en una variedad de editores de texto, limpiadores, expansores o incluso algunos administradores de portapapeles. Yo personalmente uso Sublime y TextSoap. Esta solución se creó para Text Soap, ya que vive en la barra de menú y proporciona un menú desplegable donde puede activar acciones de manipulación de texto en lo que selecciona el cursor o en el portapapeles.

Mi enfoque es esencialmente dos sustituciones / buscar y reemplazar expresiones regulares. Cada búsqueda de sustitución y reemplazo implica dos expresiones regulares, una para buscar y otra para reemplazar.

Sustitución / Buscar y reemplazar # 1

  • La primera sustitución / buscar y reemplazar elimina los números no numéricos de un número de 10 dígitos a una cadena de 10 dígitos.

Primera sustitución / búsqueda Regex:\D

  • Esta cadena de búsqueda coincide con todos los caracteres que no son dígitos.

Primera sustitución / Reemplazo Regex: "" (nada, ni siquiera un espacio)

  • Deje el campo sustituto completamente en blanco, no debe haber espacios en blanco, incluidos los espacios. Esto resultará en la eliminación de todos los caracteres coincidentes que no sean dígitos. Debería haber ingresado con 10 dígitos + caracteres de formato antes de esta operación y haber salido con 10 dígitos sin caracteres de formato.

Sustitución / Buscar y reemplazar # 2

  • La segunda sustitución / buscar y reemplazar Búsqueda parte de los grupos de capturas de operación para el código de área $1, un grupo de captura para el segundo conjunto de tres números $2, y el último grupo de captura para el último conjunto de cuatro números $3. La expresión regular de la parte sustituta de la operación inserta el formato del número de teléfono de EE. UU. Entre el grupo de dígitos capturado.

Segunda sustitución / búsqueda Regex:(\d{3})(\d{3})(\d{4})

Segunda sustitución / Reemplazo de Regex:\($1\) $2\-$3

  • La barra invertida \se escapa de los caracteres especiales (, ), (<-whitespace), y -ya que estamos insertándolos entre nuestros números capturados en grupos de captura $1, $2, y $3para fines de formato el número de teléfono de Estados Unidos.

  • En TextSoap creé un limpiador personalizado que incluye las dos acciones de operación de sustitución, por lo que en la práctica se siente idéntico a ejecutar un script. Estoy seguro de que esta solución podría mejorarse, pero espero que la complejidad aumente bastante. Una versión mejorada de esta solución es bienvenida como una experiencia de aprendizaje si alguien quiere agregar algo a esto.

Adamlogan
fuente
-2

Para números de teléfono de EE. UU.

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

Dividamos esta expresión regular en fragmentos más pequeños para que sea fácil de entender.

  • /^\(?: Significa que el número de teléfono puede comenzar con un opcional (.
  • (\d{3}): Después del opcional (debe haber 3 dígitos numéricos. Si el número de teléfono no tiene un (, debe comenzar con 3 dígitos. Por ejemplo, (308o 308.
  • \)?: Significa que el número de teléfono puede tener un opcional )después de los primeros 3 dígitos.
  • [- ]?: A continuación, el número de teléfono puede tener un guión ( -) opcional después) si está presente o después de los primeros 3 dígitos.
  • (\d{3}): Entonces debe haber 3 dígitos numéricos más. Por ejemplo, (308)-135o 308-135o308135
  • [- ]?: Después del segundo conjunto de 3 dígitos, el número de teléfono puede tener otro guión opcional ( -). Por ejemplo, (308)-135-o 308-135-o308135-
  • (\d{4})$/: Finalmente, el número de teléfono debe terminar con cuatro dígitos. Por ejemplo, (308)-135-7895o 308-135-7895o 308135-7895o3081357895 .

    Referencia:

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

Bebu
fuente
1
Copiar cosas de otros sitios web y luego ni publicar el enlace es un comportamiento bastante malo: zparacha.com/phone_number_regex
Till Helge
1
Lo siento, no tenía idea de que tenemos que publicar un enlace. Pensé que solo teníamos que proporcionar respuestas a las consultas publicadas.
Bebu
5
Es no bien hacer otro aspecto el trabajo de alguien como su propio. Recuerde para la próxima vez que no hay nada de malo en publicar enlaces, pero copiar (especialmente sin proporcionar un enlace) no lo es. Y siempre tienes la opción de editar tu respuesta.
Hasta Helge
Se votó en contra porque el autor no respondió cómo reemplazar el número de teléfono que solicitó el autor.
BrianHVB