Pregunta Una expresión regular completa para la validación del número de teléfono


Estoy tratando de armar una expresión regular completa para validar los números de teléfono. Idealmente, manejaría formatos internacionales, pero debe manejar formatos de EE. UU., 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

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


824


origen


Respuestas:


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

Luego, terminas con valores como:

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

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

  1 (234) 567-8901
  1 (234) 567-8901 x1234

482



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

Debes especificar exactamente lo que quieres. ¿Qué son los delimitadores legales? Espacios, guiones y puntos? No se permite delimitador? ¿Se pueden combinar delimitadores (por ejemplo, + 0.111-222.3333)? ¿Cómo se van a manejar las extensiones (por ejemplo, 111-222-3333 x 44444)? ¿Qué hay de los números especiales, como el 911? ¿El código de área será opcional o requerido?

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+))?$

277



.*

Si el usuario quiere darle su número de teléfono, confíe en él para hacerlo bien. Si no quiere dárselo, forzarlo a ingresar un número válido lo enviará al sitio de un competidor o le 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 de sexo de tasa superior e ingresar eso en su lugar.

También consideraría cualquiera de las siguientes 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"

274



También sugeriría mirar el "libphonenumber"Biblioteca de Google. Sé que no es Regex, pero hace exactamente lo que quieres.

Por ejemplo, reconocerá que:

15555555555

es un número posible pero no 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 Línea Fija, Móvil, Sin Costo, Tarifa Premium, Costo Compartido, VoIP y Números 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 - adivinando 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 usando información de longitud y prefijo.
  • AsYouTypeFormatterFormatea los 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 es muy dependiente culturalmente.

  • America
    • (408) 974–2042 es un válido Número de Estados Unidos
    • (999) 974–2042 es no valido Número de Estados Unidos
  • Australia
    • 0404 999 999 es un válido Número australiano
    • (02) 9999 9999 también es un válido Número australiano
    • (09) 9999 9999 es no valido Número australiano

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 el 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 utilizar una biblioteca como Google. libphonenumber (enlace al proyecto GitHub).

¡Presentando libphonenumber!

Usando uno de tus ejemplos más complejos, 1-234-567-8901 x1234, usted obtiene los siguientes datos de 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

Por lo tanto, no solo aprenderá si el número de teléfono es válido (lo cual es), sino que también obtendrá un formato de número de teléfono uniforme en su localidad.

Como extra, libphonenumber tiene una serie de conjuntos de datos para verificar la validez de los números de teléfono, así que, verificando un número como +61299999999 (la versión internacional de (02) 9999 9999) devuelve como un número válido con el 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 tomar la ubicación en la que se detecta el número de teléfono, y también obtener la información de la 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 de Google i18n:

A menos que esté seguro de que siempre va a aceptar números de una configuración regional, y siempre estarán en un formato, le recomendaría no escribir su propio código para esto y usar libphonenumber para validar y mostrar números de teléfono.


128



/^(?:(?:\(?(?: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

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


65



Aunque la respuesta para eliminar todos los espacios 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ías una expresión regular, podrías 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 de 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.

#!/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, por ejemplo, validar la entrada del usuario en un formulario cuando lo escribí, pero este cambio hace posible usar la expresión regular para ese fin.

'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*))?';

62



Respondí esta pregunta en otra pregunta de SO antes de decidir incluir también mi respuesta como respuesta en este hilo, porque nadie se estaba ocupando de cómo exigir / no requerir elementos, simplemente entregando expresiones regulares: Regex funciona mal, haciendo coincidir cosas inesperadas

Desde mi publicación en ese sitio, he creado una guía rápida para ayudar a cualquiera a hacer su propia expresión regular para su propio formato de número de teléfono deseado, lo que haré una advertencia (como hice en el otro sitio) de que si eres demasiado restrictivo, es posible que no obtenga los resultados deseados, y no existe una solución de "talla ú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.

Quick cheat sheet

  • Comience la expresión: /^ 
  • Si desea solicitar un espacio, use: [\s] o \s 
  • Si desea solicitar paréntesis, use: [(] y [)] . Utilizando \( y \) es feo y puede hacer que las cosas sean confusas.
  • Si quieres que algo sea opcional, pon un ? después de
  • Si quieres un guion, solo escribe - o [-] . Sin embargo, si no lo pones primero o último en una serie de otros personajes, es posible que tengas que escapar de él: \-
  • Si desea aceptar diferentes opciones en un espacio, coloque 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 los opcionales para ese espacio.
  • \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 esa ranura.
  • (\+|1\s)? : Acepte un "más" o un 1 y un espacio (carácter de tubería, |, es "o") y lo hace opcional. El signo "más" debe ser escapado.
  • Si desea que los números específicos coincidan con un espacio, ingréselos: [246] requerirá un 2, 4 o 6. [77|78] requerirá 77 o 78.
  • $/ : Termina la expresión

38