Cómo validar números de teléfono usando regex

920

Estoy tratando de armar una expresión regular integral para validar los números de teléfono. Idealmente, manejaría formatos internacionales, pero debe manejar formatos estadounidenses, incluidos los siguientes:

  • 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

Contestaré con mi intento actual, pero espero que alguien tenga algo mejor y / o más elegante.

Nicholas Trandem
fuente
3
Por cierto, debe especificar qué idioma está utilizando. No todos los motores de expresiones regulares tienen la misma sintaxis.
AndrewJFord
99
Parece que omitió la opción de +1 en lugar de solo 1, aunque la respuesta cubre este caso.
Eric
153
¿No requieren todos los números de teléfono de EE. UU. 555Aparte de 911?
Andrew Grimm el
41
Por el contrario, el prefijo 555 está reservado para números de teléfono falsos. Se garantiza que esos números no se conectarán a un número de teléfono real, por lo que a menudo se usan en televisión y películas para asegurarse de que el espectador no intente llamar al número y acabe acosando a algunos pobres inocentes.
rushinge
49
@rushinge Si bien eso era cierto hace décadas, ya no es cierto . El prefijo 555 sigue siendo especial, pero solo un pequeño rango de números terminará sin la conexión 555-0100 a 555-0199. Pero estoy bastante seguro de que Andrew bromeaba de todos modos.
Adam Davis

Respuestas:

515

Mejor opción ... simplemente elimine todos los caracteres que no sean dígitos en la entrada (excepto 'x' y los signos '+' iniciales), teniendo cuidado debido a la tendencia británica de escribir números en la forma no estándar +44 (0) ...cuando se le pide que use el prefijo internacional (en ese caso específico, debe descartarlo por (0)completo).

Luego, terminas con valores como:

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

Luego, cuando se muestre, vuelva a formatear el contenido de su corazón. p.ej

  1 (234) 567-8901
  1 (234) 567-8901 x1234
scunliffe
fuente
35
El código de formato será una pérdida de tiempo si se permite que los números provengan de fuera de los EE. UU.
Daniel Earwicker
26
Esto es bueno y todo, pero no valida lo que se ingresó en realidad era un número de teléfono. Por ejemplo, ¿qué pasa si el usuario no ingresa los 10 dígitos necesarios? Esto debería combinarse con una buena validación de expresiones regulares.
Hugh Jeffner
108
Teniendo en cuenta que la pregunta era sobre validación, esta es una respuesta realmente muy mala.
PlexQ
15
@PlexQ No estoy de acuerdo. El problema original está tratando de manejar la validación del número de teléfono porque estaba tratando de manejar todas las opciones de formato posibles. En lugar de tratar de resolver todo eso, tome la entrada y "elimine previamente" de toda la pelusa de formateo hasta que tenga solo el "número". Hacer esto resuelve 2 problemas: probar el resultado ahora es fácil y ahora puede asegurarse de que todos los valores que se muestran para la visualización se puedan formatear de manera coherente. El primer comentario sobre esta respuesta sobre los "Guantes del Complicador" es una buena lectura ... a veces la respuesta a un problema es abordarlo de manera diferente.
scunliffe
29
¿Cómo diablos es esta una respuesta tan votada? Esto no valida nada. Lo peor es Referencia éste todas las otras preguntas de validación de número de teléfono ...
jlars62
303

Resulta que hay algo de especificación para esto, al menos para América del Norte, llamado NANP .

Necesita especificar exactamente lo que quiere. ¿Qué son los delimitadores legales? Espacios, guiones y puntos? No se permite delimitador? ¿Se pueden mezclar delimitadores (p. Ej., + 0.111-222.3333)? ¿Cómo se manejarán las extensiones (por ejemplo, 111-222-3333 x 44444)? ¿Qué pasa con los números especiales, como el 911? ¿El código de área será opcional o obligatorio?

Aquí hay una expresión regular para un número de 7 o 10 dígitos, con extensiones permitidas, los delimitadores son espacios, guiones o puntos:

^(?:(?:\+?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+))?$
fatcat1111
fuente
77
aquí está sin la sección de extensión (hago que mis usuarios ingresen ext en un 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
Aquí hay una versión que solo coincide con números de teléfono de 10 dígitos (no 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, el
8
10 dígitos aceptan () alrededor del código de área, y no permiten el precedente 1 como código de 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.
55
@StevenSoroka He tenido el libro de Jeffrey Friedl a mi lado en mi escritorio durante los últimos dos años, ya que las expresiones regulares son una parte importante de mi trabajo. Lleva un buen tiempo entender realmente las expresiones regulares. A veces, los lectores de este sitio simplemente buscan una solución existente, en lugar de escribir la suya propia, especialmente en dominios con muchos casos de esquina, como representaciones de números de teléfono.
Justin R.
77
@ fatcat1111 Entiendo eso, pero la mayoría de las respuestas aquí son "yo también" de expresiones regulares únicas que probablemente no encajen en ninguno de sus casos de esquina. Estos terminan en todos los sitios web que estoy tratando de usar y no puedo ingresar mi código postal o número de teléfono o dirección de correo electrónico porque alguien usó una expresión regular a medias (por ejemplo: + es un carácter válido en las direcciones de correo electrónico) ) Las mejores respuestas en esta página apuntan a los usuarios a bibliotecas, no a expresiones regulares garabateadas.
Steven Soroka
298
.*

Si los usuarios quieren darte sus números de teléfono, entonces confía en ellos para acertar. Si no quieren dárselo, obligarlos a ingresar un número válido los enviará al sitio de un competidor o los hará ingresar una cadena aleatoria que se ajuste a su expresión regular. Incluso podría sentir la tentación de buscar el número de una línea directa de horóscopo de tasa premium e ingresar eso en su lugar.

También consideraría cualquiera de los siguientes como entradas válidas en un sitio web:

"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"
Dave Kirby
fuente
202
Estoy de acuerdo con el sentimiento aquí, pero a veces es bueno realizar la validación cuando el número de teléfono realmente se va a usar para algo importante en interés del usuario . El mejor ejemplo aquí es la autorización de tarjeta de crédito para una compra. Si el número de teléfono es incorrecto, la autenticación podría fallar.
Puntiagudo
53
Si el usuario no desea ingresar su número de teléfono, puede permitir que el campo sea opcional, pero ¿es demasiado pedirle al usuario que ingrese un número de teléfono válido si va a ingresar uno?
Joel McBeth
11
También una función de validación es simplemente recordar a las personas que agreguen códigos de área, etc., que de otra manera no recordarían agregar, pero que posiblemente no se pueden adivinar después del hecho.
Ben McIntyre
29
@Pointy Pero la validación de expresiones regulares no te ayudará. La única y única forma de validar si el número de teléfono es correcto es enviarle un mensaje (en el caso de un dispositivo móvil) Y asegurarse de que el usuario confirme utilizando algún tipo de código de verificación. Esto es lo que haces cuando la corrección numérica es importante. Todo lo demás es solo para comodidad del usuario para protegerse contra algunos (pero no todos) errores tipográficos y no valida nada.
Alex B
14
Frio. Mi número de teléfono es 1 'O 1 = 1 - PWNED . Ver xkcd.com/327 y owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)
Aaron Newton
171

También sugeriría mirar la biblioteca de Google " libphonenumber ". Sé que no es una expresión regular, pero hace exactamente lo que quieres.

Por ejemplo, reconocerá que:

15555555555

es un número posible pero no es un número válido. También es compatible con países fuera de los EE. UU.

Aspectos destacados de la funcionalidad:

  • Analizar / formatear / validar números de teléfono para todos los países / regiones del mundo.
  • getNumberType- obtiene el tipo del número basado en el número mismo; capaz de distinguir números fijos, móviles, gratuitos, tarifas premium, costos compartidos, VoIP y personales (siempre que sea posible).
  • isNumberMatch - obtiene un nivel de confianza sobre si dos números podrían ser iguales.
  • getExampleNumber/ getExampleNumberByType- proporciona números de ejemplo válidos para todos los países / regiones, con la opción de especificar qué tipo de número de teléfono de ejemplo se necesita.
  • isPossibleNumber - adivinar rápidamente si un número es un número de teléfono posible utilizando solo la información de longitud, mucho más rápido que una validación completa.
  • isValidNumber - validación completa de un número de teléfono para una región utilizando información de longitud y prefijo.
  • AsYouTypeFormatter - Formatea números de teléfono sobre la marcha cuando los usuarios ingresan cada dígito.
  • findNumbers - Encuentra números en la entrada de texto.
  • PhoneNumberOfflineGeocoder - proporciona información geográfica relacionada con un número de teléfono.

Ejemplos

El mayor problema con la validación del número de teléfono es que depende mucho de la cultura.

  • America
    • (408) 974–2042es un número válido de EE. UU.
    • (999) 974–2042no es un número válido de EE. UU.
  • Australia
    • 0404 999 999es un número australiano válido
    • (02) 9999 9999también es un número australiano válido
    • (09) 9999 9999no es un número australiano válido

Una expresión regular está bien para verificar el formato de un número de teléfono, pero en realidad no va a poder verificar la validez de un número de teléfono.

Sugeriría omitir una expresión regular simple para probar su número de teléfono y usar una biblioteca como Google libphonenumber(enlace al proyecto GitHub) .

¡Presentamos libphonenumber!

Usando uno de sus ejemplos más complejos, 1-234-567-8901 x1234obtiene los siguientes datos libphonenumber(enlace a la demostración en línea) :

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

Entonces, no solo aprende si el número de teléfono es válido (que es), sino que también obtiene un formato de número de teléfono consistente en su ubicación.

Como beneficio adicional, libphonenumbertiene una serie de conjuntos de datos para verificar la validez de los números de teléfono, por lo que verificar un número como +61299999999(la versión internacional de (02) 9999 9999) devuelve como un número válido con formato:

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

libphonenumber también le brinda muchos beneficios adicionales, como obtener la ubicación en la que se detecta el número de teléfono y también obtener la información de zona horaria del número de teléfono:

PhoneNumberOfflineGeocoder Results
Location        Australia

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

Pero el número de teléfono australiano no válido ( (09) 9999 9999) devuelve que no es un número de teléfono válido.

Validation Results

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

La versión de Google tiene código para Java y Javascript, pero las personas también han implementado bibliotecas para otros idiomas que usan el conjunto de datos del número de teléfono Google i18n:

A menos que esté seguro de que siempre va a aceptar números de un lugar y que siempre estarán en un formato, sugeriría encarecidamente no escribir su propio código para esto y usar el número de teléfono para validar y mostrar números de teléfono.

Tim Groeneveld
fuente
Observando que ahora también hay un puerto Go en: github.com/ttacon/libphonenumber
michaelhanson el
Al verificar si es un número posible, ¿no necesita especificar un código de país? Estoy usando la versión de PHP y si ingreso un número británico como (reemplazar 0 con números reales) 07700000000me sale un Missing or invalid default region.error. Pero si especifico el código del país, pasará.
BugHunterUK
FYI: Esta biblioteca no es compatible con algunos países, phpinterviewquestions.co.in/blog/ionic/…
sijo vijayan
1
@BugHunterUK (y cualquiera que se encuentre con esta pregunta y se pregunte lo mismo) al analizar un número, puede especificar la región esperada, y la biblioteca buscará números no internacionales en esa región. Si no especifica, rechazará todo lo que no esté en un formato internacional válido.
IMSoP
Considere github.com/nyaruka/phonenumbers ya que se ha convertido en el paquete Go "oficial" recomendado por Google en lugar de libphonenumber.
DeeZone
78

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

Esto coincide:

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

En $ n, ahorra:

  1. Indicador de país
  2. Número de teléfono
  3. Extensión

Puede probarlo en https://www.regexpal.com/?fam=99127

Ismael Miguel
fuente
Esta fue la expresión regular más completa que he visto. Es fácil moverse hasta que lo elimine ^y, de lo $contrario, puedo evitarlo usando [111] [111] [1111]o 111--111--1111y similares. (lo siento, borré mi último comentario)
bafromca
¿Puedes por favor reformular? No puedo entender esto: "Es fácil evitarlo hasta que elimine ^ y $ o de lo contrario puedo evitarlo usando [111] [111] [1111]". ¿Significa que valida '[111] [111] [1111]' cuando toma el ^y el $?
Ismael Miguel
Eludí tu expresión regular usando [111] [111] [1111]y 111--111--1111hasta que eliminé ^y $de la expresión regular.
bafromca
11
^^^ Este es un gran ejemplo de por qué los hilos de comentarios NO deberían ir al chat. Estoy muy interesado en cómo resultó esta conversación y necesito saber si este ReGex es lo suficientemente resistente como para usarlo en mi aplicación. Lamentablemente, la conversación de chat ya no está.
Matt Cashatt
1
Para ser honesto, no fui a chatear. Después de pedir explicaciones varias veces, me quedé sin información. Siempre puede probarlo usted mismo con todo tipo de números que encuentre en línea, en múltiples formatos. Una cosa que probé con este es usar varios números de teléfono, pero no funciona tan bien si tienen espacios alrededor. Y tengo que encontrar una solución para contar la cantidad de dígitos y aplicar una cantidad específica.
Ismael Miguel
63

Aunque la respuesta para eliminar todo el espacio en blanco es clara, en realidad no resuelve el problema que se plantea, que es encontrar una expresión regular. Tomemos, por ejemplo, mi script de prueba que descarga una página web y extrae todos los números de teléfono usando la expresión regular. Como de todos modos necesitaría una expresión regular, también podría hacer que la expresión regular haga todo el trabajo. Se me ocurrió esto:

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

Aquí hay un script perl para probarlo. Cuando coincide, $ 1 contiene el código de área, $ 2 y $ 3 contienen el número de teléfono y $ 5 contiene la extensión. Mi script de prueba descarga un archivo de Internet e imprime todos los números de teléfono que contiene.

#!/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:

Puede cambiar \ W * a \ s * \ W? \ S * en la expresión regular para ajustarlo un poco. No estaba pensando en la expresión regular en términos de, digamos, validar la entrada del usuario en un formulario cuando lo escribí, pero este cambio hace posible usar la expresión regular para ese propósito.

'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*))?';
indiv
fuente
2
Para su información, la expresión regular también coincide: lo (4570457-6789que sería un error tipográfico bastante común. Los grupos de partidos también se sesgan
SooDesuNe
@SooDesuNe Prepending (^|[^\d\n])(con el indicador multilínea activado ) evita el problema general al garantizar que no esté precedido inmediatamente por algo numérico.
btown
Tenga en cuenta que esto está centrado en América del Norte - se pierde "44 7911 123456"
Ben Wheeler
43

Respondí esta pregunta en otra pregunta SO antes de decidir incluir también mi respuesta como respuesta en este hilo, porque nadie estaba abordando cómo requerir / no requerir elementos, solo repartía expresiones regulares: Regex funciona mal, coincide con cosas inesperadas

A partir de mi publicación en ese sitio, he creado una guía rápida para ayudar a cualquier persona a hacer su propia expresión regular para su propio formato de número de teléfono deseado, lo que advertiré (como hice en el otro sitio) que si eres demasiado restrictivo, es posible que no obtenga los resultados deseados, y no hay una solución única para aceptar todos los números de teléfono posibles en el mundo, solo lo que decida aceptar como su formato de elección. Úselo bajo su propio riesgo.

Hoja de trucos rápida

  • Comience la expresión: /^
  • Si desea requerir un espacio, use: [\s]o\s
  • Si desea requerir paréntesis, use: [(]y [)]. Usar \(y \)es feo y puede hacer que las cosas sean confusas.
  • Si quieres que algo sea opcional, pon un ?después
  • Si quieres un guión, solo escribe -o [-]. Sin embargo, si no lo coloca primero o último en una serie de otros caracteres, es posible que deba escapar de él: \-
  • Si desea aceptar diferentes opciones en un espacio, ponga corchetes alrededor de las opciones: [-.\s]requerirá un guión, punto o espacio. Un signo de interrogación después del último paréntesis hará que todos sean opcionales para esa ranura.
  • \d{3}: Requiere un número de 3 dígitos: 000-999. Taquigrafía para [0-9][0-9][0-9].
  • [2-9] : Requiere un dígito 2-9 para ese espacio.
  • (\+|1\s)?: Acepte un "más" o un 1 y un espacio (carácter de canalización |, es "o") y hágalo opcional. El signo "más" debe escaparse.
  • Si desea que números específicos coincidan con un espacio, ingréselos: [246]requerirá un 2, 4 o 6. [77|78]requerirá 77 o 78.
  • $/ : Finaliza la expresión
vapcguy
fuente
1
Esto es muy útil, pero dudo y busco una expresión {min, max}. ¿Puede usted ayudar?
Ataboy Josef
Si estamos hablando de un solo dígito (y puede hacer que coincida de acuerdo con eso), vea el [2-9]bloque que puse allí. Eso significa que su mínimo es 2 y su máximo es 9. Ajuste en consecuencia.
vapcguy
30

Escribí lo más simple (aunque no necesitaba punto).

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

Como se menciona a continuación, verifica solo los caracteres, no su estructura / orden

rev. Artjom Kurapov
fuente
38
esto valida toneladas de números que son técnicamente inválidos. como "- + () () ()) ())))". Aprende a leer expresiones regulares para que puedas entender lo que estás haciendo.
Steven Soroka
3
@StevenSoroka técnicamente puede permitir muchos casos inválidos, pero cuando pensamos en ayudar al usuario a evitar errores comunes con la solución más simple posible, este es el camino a seguir :)
happyhardik
2
esto también coincide con el espacio en blanco, línea vacía
Wasim A.
1
@HappyHardik. En efecto. Simple y potente, para la validación básica, permite al usuario escribir más de un punto, guión, paréntesis o más.
Dijipiji
Solo lo usé y está mal en muchos aspectos. Por ejemplo, un número de teléfono del Reino Unido puede comenzar con +44, o un número de teléfono puede tener (0) dentro. Pero esto no es válido según su expresión regular. Recomendaría la respuesta de @Ismael Miguel. Funciona bien y le recomendaría que revise su respuesta.
Stelios Voskos
22

Si solo quiere verificar que no tiene basura aleatoria en el campo (es decir, de formadores de spam), esta expresión regular debería funcionar bien:

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

Tenga en cuenta que no tiene reglas especiales para cuántos dígitos, o qué números son válidos en esos dígitos, solo verifica que solo dígitos, paréntesis, guiones, más, espacio, libra, asterisco, punto, coma o las letras e, x, testán presentes.

Debe ser compatible con números internacionales y formatos de localización. ¿Prevé alguna necesidad de permitir paréntesis cuadrados, rizados o angulados para algunas regiones? (actualmente no están incluidos).

Si desea mantener reglas por dígito (como en los códigos de área y prefijos de EE. UU. (Códigos de intercambio) deben estar en el rango de 200-999), buena suerte. Mantener un conjunto de reglas complejas que podría estar desactualizado en cualquier momento en el futuro por cualquier país del mundo no suena divertido.

Y si bien la eliminación de todos / la mayoría de los caracteres no numéricos puede funcionar bien en el lado del servidor (especialmente si planea pasar estos valores a un marcador), es posible que no desee anular la entrada del usuario durante la validación, especialmente si desea que hacer correcciones en otro campo.

Steve
fuente
22

Tenga en cuenta que la eliminación de ()caracteres no funciona para un estilo de escritura de números del Reino Unido que es común: lo +44 (0) 1234 567890que significa marcar el número internacional:
+441234567890
o en el marcado del Reino Unido01234567890

Ben Clifford
fuente
15

¿Has echado un vistazo a RegExLib ?

Ingresar el número de teléfono de EE. UU. Trajo una lista de posibilidades.

Rob Wells
fuente
3
Esto parece una excelente manera de integrar errores oscuros en su código.
Tom Lord
12

Mi intento de una expresión regular no restrictiva:

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

Acepta:

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

Rechaza:

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

Depende de usted desinfectarlo para mostrarlo. Sin embargo, después de validar podría ser un número.

ReactiveRaven
fuente
12

Encontré que esto funciona bastante bien:

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

Funciona para estos formatos de números:

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

Asegúrese de utilizar banderas globales Y multilíneas para asegurarse.

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

Herobrine2Nether
fuente
11

Si está hablando de la validación de formularios, la expresión regular para validar el significado correcto y los datos correctos será extremadamente compleja debido a los diferentes estándares de país y proveedor. También será difícil mantenerse al día.

Interpreto la pregunta como la búsqueda de un patrón ampliamente válido, que puede no ser internamente consistente, por ejemplo, tener un conjunto válido de números, pero no validar que la línea troncal, el intercambio, etc. al patrón válido para el prefijo del código de país .

América del Norte es sencillo, y para internacional prefiero usar un patrón 'idiomático' que cubra las formas en que las personas especifican y recuerdan sus números:

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

El patrón de América del Norte asegura que si se incluye un paréntesis, ambos están incluidos. Las cuentas internacionales para un '+' inicial opcional y código de país. Después de eso, estás en el idioma. Las coincidencias válidas serían:

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

Esto puede ser parcial ya que mi experiencia se limita a América del Norte, Europa y un poco de Asia.

ron0
fuente
He estado tratando de implementar lo anterior en mi script de validación de JavaScript, pero sigo recibiendo un invalid quantifiererror. ¿Alguna idea sobre lo que estoy haciendo mal?
Jannis
Agregaría el caso trivial donde el teléfono se especifica sin símbolos pero tal vez espacios y código de país, en Europa es típico para números locales y móviles: 676412342, 676 46 32 12, 676 463 212
rompe el
11

Aquí hay un patrón maravilloso que se parecía más a la validación que necesitaba lograr. No soy el autor original, pero creo que vale la pena compartirlo ya que este problema me pareció muy complejo y sin una respuesta concisa o muy útil.

La siguiente expresión regular capturará combinaciones de números y caracteres ampliamente utilizados en una variedad de formatos de números de teléfono globales:

/^\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

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

Stuart Kershaw
fuente
Esto tiene un soporte limitado para extensiones. Coincide con "616-555-1234 x567" pero no con "616-555-1234 ext. 567".
Jon Schneider
2
Falso positivo para, por ejemplo, "------- (((((((55555555" o "99999999999999999999999"
mikep
No valida el número de MacDonalds de Noruega +31 76 596 4192 (solo estaba probando números aleatorios)
BIOHAZARD
10

Mi instinto se ve reforzado por la cantidad de respuestas a este tema: que hay un número prácticamente infinito de soluciones a este problema, ninguna de las cuales será elegante.

Honestamente, recomendaría que no intentes validar los números de teléfono. Incluso si pudieras escribir un validador grande y peludo que permitiera todos los diferentes formatos legítimos, terminaría permitiendo prácticamente cualquier cosa, incluso remotamente parecida a un número de teléfono en primer lugar.

En mi opinión, la solución más elegante es validar una longitud mínima, nada más.

mindplay.dk
fuente
Después de probar varios de estos y revisar los datos existentes y los comentarios de los usuarios, tendería a aceptar ...
Christopher King
Sin embargo, a veces es necesario validar. Si envío códigos de confirmación, no puedo enviar un código a cualquier basura aleatoria que haya ingresado un spammer en el campo. Quiero asegurarme de que el número sea probablemente un número de teléfono antes de desperdiciar recursos enviándolo.
Lucas
10

Este es un patrón de expresión regular simple para números de teléfono móvil de Filipinas:

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

o

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

coincidirá con estos:

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

El primero coincidirá con CUALQUIER código de país de dos dígitos, mientras que el segundo coincidirá exclusivamente con el código de país de Filipinas.

Pruébelo aquí: http://refiddle.com/1ox

GaiusSensei
fuente
Gracias. ¿Qué hay de los números de teléfono fijo con código de área como 028231234? Me pregunto si los códigos de área son solo números de 2-3 dígitos y ¿siempre están precedidos por 0?
stormwild
9

Aquí está mi mejor intento hasta ahora. Maneja los formatos anteriores, pero estoy seguro de que me faltan algunos otros formatos posibles.

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

Te resultará difícil tratar con números internacionales con una expresión regular simple / simple, mira esta publicación sobre las dificultades de los números de teléfono internacionales (e incluso norteamericanos).

Deberá analizar los primeros dígitos para determinar cuál es el código del país y luego actuar de manera diferente según el país.

Más allá de eso, la lista que proporcionó no incluye otro formato común en los EE. UU., Dejando de lado el 1. inicial. La mayoría de los teléfonos celulares en los EE. UU. No lo requieren, y comenzará a desconcertar a la generación más joven a menos que hayan marcado internacionalmente.

Has identificado correctamente que es un problema complicado ...

-Adán

Adam Davis
fuente
No es una solución ofrecida. ES POSIBLE. El hecho de que sea complicado o complejo no significa que solo debas levantar los brazos.
Eric Hodonsky
7

Después de leer estas respuestas, parece que no había una expresión regular directa que pueda analizar un montón de texto y extraer números de teléfono en cualquier formato (incluidos los internacionales con y sin el signo más).

Esto es lo que usé para un proyecto de cliente recientemente, donde tuvimos que convertir todos los números de teléfono en cualquier formato a tel: links.

Hasta ahora, ha estado trabajando con todo lo que le han arrojado, pero si surgen errores, actualizaré esta respuesta.

Expresión regular:

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

Función PHP para reemplazar todos los números de teléfono con tel: links (en caso de que alguien tenga curiosidad):

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;
}
Drew Thomas
fuente
Esta expresión regular coincidía +1 1234562222222222222222222222.
Varda Elentári
¿Por qué no simplemente volver?
thexande
Falso positivo para "999999999999999999999999999999999999999"
Ben Wheeler
6

Creo que los módulos de Perl Number :: Phone :: US y Regexp :: Common (particularmente la fuente de Regexp :: Common :: URI :: RFC2806 ) podrían ayudar.

La pregunta probablemente debería especificarse con un poco más de detalle para explicar el propósito de validar los números. Por ejemplo, 911 es un número válido en los EE. UU., Pero 911x no es para ningún valor de x. Eso es para que la compañía telefónica pueda calcular cuándo terminaste de marcar. Hay varias variaciones sobre este tema. Pero su expresión regular no verifica la parte del código de área, por lo que no parece ser una preocupación.

Al igual que validar direcciones de correo electrónico, incluso si tiene un resultado válido, no puede saber si está asignado a alguien hasta que lo pruebe.

Si está intentando validar la entrada del usuario, ¿por qué no normalizar el resultado y terminarlo? Si el usuario ingresa un número que no puede reconocer como un número válido, guárdelo como ingresado o elimine los caracteres no disponibles. El módulo Number :: Phone :: Normalize Perl podría ser una fuente de inspiración.

Jon Ericson
fuente
Voy a arriesgarme aquí y decir que permitir 911 como número de teléfono es probablemente una mala idea en casi todas las aplicaciones de esta expresión regular. Buena captura sin embargo.
Nicholas Flynt
4

Trabajo para una empresa de investigación de mercado y tenemos que filtrar este tipo de información todo el tiempo. Lo estás complicando demasiado. Simplemente elimine los caracteres no alfanuméricos y vea si hay una extensión.

Para un análisis más detallado, puede suscribirse a uno de los muchos proveedores que le darán acceso a una base de datos de números válidos, así como decirle si son teléfonos fijos o móviles, desconectados, etc. Cuesta dinero.

Joe Phillips
fuente
¿Validación? 123% $) *% () $ * () # 456 * () * $ # (* (# $ @ 8908 coincidiría con su solución propuesta.
PlexQ
1
@PlexQ 555-123-1234, 07777777777, 90210, 01/01/1901: los usuarios son ingeniosos para embestir basura a través de la validación. Es mejor no marcar a los que realmente tienen datos extraños utilizando una validación demasiado restrictiva y diciéndoles que están equivocados.
ReactiveRaven
4

Reemplace los caracteres de formato, luego verifique la validez del teléfono restante. En PHP

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

Romper una expresión regular compleja como esta puede ser igual de efectivo, pero mucho más simple.

Rooskie
fuente
3

Encontré que esto es algo interesante. No lo he probado pero parece que funcionaría

<?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.';
}
?>
Chris
fuente
44
Su mensaje parece indicar que no escribió este código. ¿Te importaría citar una fuente, por favor?
Alastair Irvine
bitrepository.com/how-to-validate-a-telephone-number.html parece ser la fuente.
James Paterson el
3

Probablemente sería mejor usar una entrada enmascarada para esto. De esa manera, los usuarios SOLO pueden ingresar números y usted puede formatear como mejor le parezca. No estoy seguro de si esto es para una aplicación web, pero si es así, hay un complemento jQuery con un solo clic que ofrece algunas opciones para hacerlo.

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

Incluso explican cómo enmascarar entradas de números de teléfono en su tutorial.

Abe Miessler
fuente
3

Aquí hay uno que funciona bien en JavaScript. Está en una cadena porque eso era lo que esperaba el widget Dojo.

Coincide con un número NANP de América del Norte de 10 dígitos con extensión opcional. Los espacios, guiones y puntos son delimitadores aceptados.

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

Estaba luchando con el mismo problema, tratando de hacer que mi aplicación sea a prueba de futuro, pero estos tipos me llevaron en la dirección correcta. En realidad no estoy verificando el número en sí para ver si funciona o no, solo estoy tratando de asegurarme de que se ingresó una serie de números que pueden tener o no una extensión.

En el peor de los casos, si el usuario tuviera que extraer un número sin formato del archivo XML, seguiría escribiendo los números en el teclado numérico del teléfono 012345678x5, no hay razón real para mantenerlo bonito. Ese tipo de RegEx saldría algo así para mí:

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

Mi inclinación es aceptar que despojar a los no dígitos y simplemente aceptar lo que hay es lo mejor. Tal vez para garantizar que haya al menos un par de dígitos, aunque eso prohíbe algo como un número de teléfono alfabético "ASK-JAKE", por ejemplo.

Un par de expresiones perl simples pueden ser:

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

Use el primero para mantener juntos los grupos de dígitos, lo que puede dar pistas de formato. Use el segundo para tirar trivialmente todos los no dígitos.

¿Es preocupante que deba haber una pausa y luego ingresar más claves? ¿O algo así como 555-1212 (espera el pitido) 123?

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

Debe terminar con un dígito, puede comenzar con (o + o un dígito, y puede contener + - (o)

Ian
fuente
2

Para cualquier persona interesada en hacer algo similar con los números de teléfonos móviles irlandeses, aquí hay una forma sencilla de lograrlo:

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

También hay una solución JQuery en ese enlace.

EDITAR:

Solución 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();
});


});

Fuente .

Lajos Arpad
fuente