Come convalidare i numeri di telefono usando regex


920

Sto cercando di mettere insieme una regex completa per convalidare i numeri di telefono. Idealmente dovrebbe gestire i formati internazionali, ma deve gestire i formati statunitensi, inclusi i seguenti:

  • 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

Risponderò con il mio attuale tentativo, ma spero che qualcuno abbia qualcosa di meglio e / o più elegante.


3
A proposito, dovresti specificare quale lingua stai usando. Non tutti i motori regex hanno la stessa sintassi.
AndrewJFord,

9
Sembra che tu abbia tralasciato l'opzione +1 anziché solo 1, anche se la risposta copre questo caso.
Eric,

153
Non sono richiesti tutti i numeri di telefono statunitensi 555a parte loro 911?
Andrew Grimm,

41
Al contrario, il prefisso 555 è riservato ai numeri di telefono falsi. Questi numeri sono garantiti per non connettersi a un numero di telefono reale, quindi vengono spesso utilizzati in televisione e nei film per garantire che uno spettatore non provi a chiamare il numero e finisca per molestare alcuni poveri innocenti.
rushinge,

49
@rushinge Anche se era vero decenni fa, non è più vero . Il prefisso 555 è ancora speciale, ma è garantito che solo un piccolo intervallo di numeri termini senza connessione da 555-0100 a 555-0199. Ma sono abbastanza sicuro che Andrew stesse scherzando comunque.
Adam Davis,

Risposte:


515

Opzione migliore ... basta rimuovere tutti i caratteri non digitati sull'input (tranne i segni "x" e "+" iniziali), prestando attenzione a causa della tendenza britannica a scrivere numeri in formato non standard +44 (0) ...quando viene chiesto di utilizzare il prefisso internazionale (in quel caso specifico, dovresti scartare del (0)tutto).

Quindi, finisci con valori come:

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

Quindi quando visualizzi, riformatta il contenuto del tuo cuore. per esempio

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

35
Il codice di formattazione sarà una perdita di tempo se i numeri possono arrivare al di fuori degli Stati Uniti.
Daniel Earwicker,

26
Questo è buono e tutto, ma non convalida ciò che è stato inserito era in realtà un numero di telefono. Ad esempio, cosa succede se l'utente non inserisce le 10 cifre richieste? Questo dovrebbe essere combinato con una buona convalida regex.
Hugh Jeffner,

108
Considerando che la domanda riguardava la convalida: questa è una risposta davvero pessima.
PlexQ,

15
@PlexQ Non sono d'accordo. Il problema originale sta provando a gestire la convalida del numero di telefono perché stava cercando di gestire tutte le possibili opzioni di formattazione. Invece di provare a risolvere tutto ciò, prendi l'input e "pre-strip" di tutto il fluff di formattazione fino a quando non hai solo il "numero". In questo modo si risolvono 2 problemi: testare il risultato ora è facile e ora puoi assicurarti che i valori restituiti per la visualizzazione possano essere formattati in modo coerente. Il primo commento su questa risposta sui "Complicator's Gloves" è una buona lettura ... a volte la risposta a un problema è affrontarla in modo diverso.
scunliffe,

29
Come diavolo è una risposta così votata? Questo non convalida nulla. Quel che è peggio è che tutte le altre domande di convalida del numero di telefono fanno riferimento a questo ...
jlars62

303

Si scopre che esiste qualcosa di specifico per questo, almeno per il Nord America, chiamato NANP .

Devi specificare esattamente quello che vuoi. Cosa sono i delimitatori legali? Spazi, trattini e punti? Nessun delimitatore consentito? Si possono mescolare delimitatori (ad es. + 0,111-222,3333)? Come verranno gestite le estensioni (ad es. 111-222-3333 x 44444)? E i numeri speciali, come il 911? Il prefisso sarà facoltativo o obbligatorio?

Ecco una regex per un numero di 7 o 10 cifre, con estensioni consentite, i delimitatori sono spazi, trattini o punti:

^(?:(?:\+?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+))?$

7
qui è senza la sezione di estensione (faccio in modo che i miei utenti inseriscano ext in un campo separato): ^ (?: (?: \ +? 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
Ecco una versione che corrisponde solo a numeri di telefono a 10 cifre (non a 7 cifre come 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

8
10 cifre accetta () intorno al prefisso e non consentire la precede 1 come prefisso internazionale(?:(?:(\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.

5
@StevenSoroka Ho avuto il libro di Jeffrey Friedl accanto a me sulla mia scrivania negli ultimi due anni, poiché le espressioni regolari sono una parte importante del mio lavoro. Ci vuole molto tempo per capire davvero le espressioni regolari. A volte, i lettori di questo sito sono semplicemente alla ricerca di una soltuion esistente, piuttosto che scrivere la propria, specialmente in domini con molti casi angolari, come le rappresentazioni dei numeri di telefono.
Justin R.,

7
@ fatcat1111 Lo capisco, ma la maggior parte delle risposte qui sono del tipo "anch'io" di espressioni regolari una tantum che probabilmente non si adattano a nessuno dei tuoi casi angolari. Questi poi finiscono su tutti i siti Web che sto cercando di utilizzare e non riesco a inserire il mio codice postale o numero di telefono o indirizzo e-mail perché qualcuno ha usato un'espressione regolare cotta a metà (ad es. ). Le migliori risposte in questa pagina indirizzano gli utenti alle librerie, non alle regex scarabocchiate di tovaglioli.
Steven Soroka,

298
.*

Se gli utenti vogliono darti i loro numeri di telefono, fidati di loro per farlo bene. Se non vogliono dartelo, costringendoli a inserire un numero valido li invieranno al sito di un concorrente o li faranno inserire una stringa casuale adatta al tuo regex. Potrei anche essere tentato di cercare il numero di una linea diretta per oroscopo a tariffa premium e inserirla invece.

Vorrei anche considerare una delle seguenti voci valide su un sito 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"

202
Sono d'accordo con il sentimento qui, ma a volte è bello eseguire la convalida quando il numero di telefono verrà effettivamente utilizzato per qualcosa di importante nell'interesse dell'utente . Il miglior esempio qui è l'autorizzazione della carta di credito per un acquisto. Se il numero di telefono è errato, l'autenticazione potrebbe non riuscire.
Punta il

53
Se l'utente non desidera inserire il proprio numero di telefono, è possibile consentire che il campo sia facoltativo, ma è troppo chiedere all'utente di inserire un numero di telefono valido se ne inserirà uno?
Joel McBeth,

11
Anche un ruolo di convalida è semplicemente quello di ricordare alle persone di aggiungere prefissi ecc. Che altrimenti potrebbero non ricordare di aggiungere, ma che non è possibile indovinare dopo il fatto.
Ben McIntyre,

29
@Pointy Ma la convalida regex non ti aiuterà. L'unico e unico modo per convalidare effettivamente se il numero di telefono è corretto è effettivamente inviargli un messaggio (nel caso del cellulare) E assicurarsi che l'utente confermi utilizzando un qualche tipo di codice di verifica. Questo è ciò che fai quando la correttezza dei numeri è importante. Tutto il resto è solo per comodità dell'utente proteggere da alcuni (ma non tutti) errori di battitura e non convalida nulla.
Alex B,

14
Freddo. Il mio numero di telefono è 1 'O 1 = 1 - PWNED . Vedi xkcd.com/327 e owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)
Aaron Newton,

171

Vorrei anche suggerire di guardare la libreria di Google " libphonenumber ". So che non è regex ma fa esattamente quello che vuoi.

Ad esempio, riconoscerà che:

15555555555

è un numero possibile ma non un numero valido. Supporta anche paesi al di fuori degli Stati Uniti.

Punti salienti della funzionalità:

  • Analisi / formattazione / convalida dei numeri di telefono per tutti i paesi / regioni del mondo.
  • getNumberType- ottiene il tipo di numero in base al numero stesso; in grado di distinguere numeri fissi, mobili, numeri verdi, tariffe premium, costi condivisi, VoIP e numeri personali (ove possibile).
  • isNumberMatch - ottiene un livello di confidenza se due numeri potrebbero essere uguali.
  • getExampleNumber/ getExampleNumberByType- fornisce numeri di esempio validi per tutti i paesi / regioni, con la possibilità di specificare quale tipo di numero di telefono di esempio è necessario.
  • isPossibleNumber - indovinare rapidamente se un numero è un numero di telefono possibile utilizzando solo le informazioni sulla lunghezza, molto più velocemente di una convalida completa.
  • isValidNumber - convalida completa di un numero di telefono per una regione utilizzando informazioni su lunghezza e prefisso.
  • AsYouTypeFormatter - formatta i numeri di telefono al volo quando gli utenti inseriscono ciascuna cifra.
  • findNumbers - trova numeri nell'inserimento di testo.
  • PhoneNumberOfflineGeocoder - fornisce informazioni geografiche relative a un numero di telefono.

Esempi

Il problema più grande con la convalida del numero di telefono è che dipende molto dalla cultura.

  • America
    • (408) 974–2042è un numero USA valido
    • (999) 974–2042non è un numero USA valido
  • Australia
    • 0404 999 999è un numero australiano valido
    • (02) 9999 9999è anche un numero australiano valido
    • (09) 9999 9999non è un numero australiano valido

Un'espressione regolare va bene per controllare il formato di un numero di telefono, ma in realtà non sarà in grado di verificare la validità di un numero di telefono.

Suggerirei di saltare una semplice espressione regolare per testare il tuo numero di telefono e di utilizzare una libreria come quella di Google libphonenumber(link al progetto GitHub) .

Presentazione di libphonenumber!

Utilizzando uno dei tuoi esempi più complessi, 1-234-567-8901 x1234ottieni i seguenti dati da libphonenumber(link alla demo online) :

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

Quindi non solo impari se il numero di telefono è valido (quale è), ma ottieni anche una formattazione coerente del numero di telefono nella tua lingua.

Come bonus, libphonenumberha un numero di set di dati per verificare la validità dei numeri di telefono, quindi controllando un numero come +61299999999(la versione internazionale di (02) 9999 9999) si restituisce un numero valido con formattazione:

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 ti offre anche molti altri vantaggi, come la presa della posizione in cui viene rilevato il numero di telefono e anche ottenere le informazioni sul fuso orario dal numero di telefono:

PhoneNumberOfflineGeocoder Results
Location        Australia

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

Ma il numero di telefono australiano non valido ( (09) 9999 9999) restituisce che non è un numero di telefono valido.

Validation Results

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

La versione di Google ha codice per Java e Javascript, ma le persone hanno anche implementato librerie per altre lingue che utilizzano il set di dati del numero di telefono di Google i18n:

A meno che non si sia certi di accettare sempre numeri da una locale e che siano sempre in un formato, suggerirei vivamente di non scrivere il proprio codice per questo e di utilizzare libphonenumber per convalidare e visualizzare i numeri di telefono.


Notando che ora c'è anche il porto di Go su: github.com/ttacon/libphonenumber
michaelhanson

Quando si verifica se è un numero possibile, non è necessario specificare un prefisso internazionale? Sto usando la versione di PHP e se inserisco un numero britannico come (sostituisci gli 0 con i numeri reali) 07700000000ottengo un Missing or invalid default region.errore. Ma se specifico il prefisso nazionale passerà.
BugHunterUK,

FYI: Questa libreria non supporta alcuni paesi, phpinterviewquestions.co.in/blog/ionic/…
sijo vijayan,

1
@BugHunterUK (e chiunque incontri questa domanda e si chieda lo stesso) quando analizza un numero, puoi specificare la regione prevista e la biblioteca cercherà numeri non internazionali in quella regione. Se non specifichi, rifiuterà tutto ciò che non è in un formato internazionale valido.
IMSoP

Prendi in considerazione github.com/nyaruka/phonenumbers in quanto è diventato il pacchetto Go "ufficiale" consigliato da Google anziché da libphonenumber.
DeeZone,

78

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

Questo corrisponde:

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

Su $ n, salva:

  1. Indicatore del paese
  2. Numero di telefono
  3. Estensione

Puoi provarlo su https://www.regexpal.com/?fam=99127


Questa è stata la regex più completa che abbia mai visto. È facile andare in giro fino a quando non lo rimuovi ^e $altrimenti non sono in grado di aggirarlo usando [111] [111] [1111]o 111--111--1111e simili. (scusate, ho eliminato il mio ultimo commento)
bafromca il

Puoi per favore ripetere la frase? Non riesco a capirlo: "È facile trovarsi in giro finché non si rimuovono ^ e $ oppure non sono in grado di aggirarlo usando [111] [111] [1111]". Significa che convalida '[111] [111] [1111]' quando prendi il ^e il $?
Ismael Miguel,

Ho aggirato il tuo regex usando [111] [111] [1111]e 111--111--1111fino a quando non l'ho rimosso ^e $dal regex.
bafromca,

11
^^^ Questo è un ottimo esempio del perché i thread dei commenti NON dovrebbero andare in chat. Sono molto interessato a come è nata questa conversazione e devo sapere se questo ReGex è abbastanza robusto da poter essere utilizzato nella mia app. Sfortunatamente, la conversazione di chat ora è andata.
Matt Cashatt,

1
Ad essere sincero, non sono andato a chattare. Dopo aver chiesto più volte spiegazioni, non ho avuto informazioni. Puoi sempre provarlo tu stesso con tutti i tipi di numeri che trovi online, in più formati. Una cosa che ho provato con questo è usare più numeri di telefono, ma non funziona così bene se hanno spazi intorno. E devo trovare una soluzione per contare la quantità di cifre e applicare una quantità specifica.
Ismael Miguel,

63

Sebbene la risposta per eliminare tutti gli spazi bianchi sia chiara, in realtà non risolve il problema che si pone, ovvero trovare una regex. Prendi, ad esempio, il mio script di test che scarica una pagina Web ed estrae tutti i numeri di telefono usando regex. Dato che avresti bisogno comunque di una regex, potresti anche fare in modo che la regex faccia tutto il lavoro. Ho pensato a questo:

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

Ecco uno script perl per testarlo. Quando abbini, $ 1 contiene il prefisso, $ 2 e $ 3 contengono il numero di telefono e $ 5 contiene l'estensione. Il mio script di test scarica un file da Internet e stampa tutti i numeri di telefono al suo interno.

#!/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";
        }
}

Modificare:

Puoi cambiare \ W * in \ s * \ W? \ S * nella regex per stringere un po '. Non pensavo alla regex in termini, per esempio, di convalida dell'input dell'utente su un modulo quando l'ho scritto, ma questa modifica rende possibile usare la regex a tale scopo.

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

2
Cordiali saluti, il regex corrisponde anche: (4570457-6789che sarebbe un errore di battitura piuttosto comune. Anche i gruppi di partite sono distorti
SooDesuNe

@SooDesuNe Prepending (^|[^\d\n])(con il flag multilinea attivato ) evita il problema generale, assicurandosi che non sia immediatamente preceduto da qualcosa di numerico.
btown

Nota che questo è incentrato sul Nord America - manca "44 7911 123456"
Ben Wheeler

43

Ho risposto a questa domanda su un'altra domanda SO prima di decidere di includere anche la mia risposta come risposta su questo thread, perché nessuno si stava rivolgendo a come richiedere / non richiedere elementi, distribuendo solo regex : Regex funzionava male, abbina cose inaspettate

Dal mio post su quel sito, ho creato una guida rapida per aiutare chiunque a creare la propria regex per il proprio formato di numero di telefono desiderato, che avvertirò (come ho fatto sull'altro sito) che se sei troppo restrittivo, potresti non ottenere i risultati desiderati e non esiste una soluzione "taglia unica" per accettare tutti i possibili numeri di telefono nel mondo, solo ciò che decidi di accettare come formato di scelta. Utilizzare a proprio rischio.

Cheat sheet veloce

  • Inizia l'espressione: /^
  • Se si desidera richiedere uno spazio, utilizzare: [\s]o\s
  • Se si desidera richiedere la parentesi, utilizzare: [(]e [)]. utilizzando\( e \)è brutto e può creare confusione.
  • Se vuoi che qualcosa sia facoltativo, inserisci a ? dopo
  • Se vuoi un trattino, digita -o[-] . Se non lo metti per primo o per ultimo in una serie di altri personaggi, potresti dover scappare: \-
  • Se vuoi accettare diverse scelte in uno slot, metti le parentesi attorno alle opzioni: [-.\s] richiederà un trattino, un punto o uno spazio. Un punto interrogativo dopo l'ultima parentesi renderà tutte quelle opzionali per quello slot.
  • \d{3}: Richiede un numero di 3 cifre: 000-999. Stenografia per [0-9][0-9][0-9] .
  • [2-9] : Richiede una cifra 2-9 per quello slot.
  • (\+|1\s)? : Accetta un "più" o un 1 e uno spazio (carattere pipe, | , è "o") e rendilo facoltativo. Il segno "più" deve essere sfuggito.
  • Se si desidera che numeri specifici corrispondano a uno slot, inserirli: [246]richiederà un 2, 4 o 6. [77|78]richiederà 77 o 78.
  • $/ : Termina l'espressione

1
Questo è molto utile, ma dubito e cerco un'espressione {min, max}. Puoi aiutare?
Ataboy Josef,

Se si tratta di una sola cifra di cui stiamo parlando (e puoi farla corrispondere in base a ciò), vedi il [2-9]blocco che ho inserito lì. Ciò significa che il tuo min è 2 e il tuo massimo è 9. Regola di conseguenza.
vapcguy,

30

Ho scritto più semplice (anche se non avevo bisogno di un punto).

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

Come menzionato di seguito, controlla solo i caratteri, non la sua struttura / ordine


38
ciò convalida tonnellate di numeri tecnicamente non validi. come, "- + () () ()) ())))". Impara a leggere le espressioni regolari in modo da poter capire cosa stai facendo.
Steven Soroka,

3
@StevenSoroka tecnicamente può consentire molti casi non validi, ma quando pensiamo di aiutare l'utente a evitare errori comuni con la soluzione più semplice possibile, questa è la strada da percorrere :)
happyhardik

2
questo eguaglia anche lo spazio bianco, la linea vuota
Wasim A.

1
@HappyHardik. Infatti. Semplice e potente, per la convalida di base lascia che l'utente digiti più di un punto, trattino, parentesi o più.
dijipiji,

L'ho appena usato ed è sbagliato sotto molti aspetti. Ad esempio, un numero di telefono nel Regno Unito può iniziare con +44 o un numero di telefono può contenere (0) al suo interno. Ma questo non è valido secondo la tua espressione regolare. Consiglierei la risposta di @Ismael Miguel. Funziona bene e ti consiglio di rivedere la tua risposta.
Stelios Voskos,

22

Se vuoi solo verificare di non avere immondizia casuale nel campo (ad esempio, dagli spammer dei moduli), questa regex dovrebbe fare bene:

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

Nota che non ha regole speciali per quante cifre o quali numeri sono validi in quelle cifre, verifica solo che solo cifre, parentesi, trattini, più, spazio, cancelletto, asterisco, punto, virgola o lettere e, x, tsono presenti.

Dovrebbe essere compatibile con numeri internazionali e formati di localizzazione. Prevedi la necessità di consentire parentesi quadre, ricci o inclinate per alcune regioni? (al momento non sono inclusi).

Se vuoi mantenere le regole per cifra (come nei prefissi e prefissi statunitensi (codici di scambio) deve rientrare nell'intervallo 200-999), buona fortuna a te. Mantenere un complesso insieme di regole che potrebbe essere superato in qualsiasi momento in futuro da qualsiasi paese del mondo non sembra divertente.

E mentre lo stripping di tutti / la maggior parte dei caratteri non numerici può funzionare bene sul lato server (specialmente se stai pianificando di passare questi valori a un dialer), potresti non voler bloccare l'input dell'utente durante la convalida, in particolare se lo desideri apportare correzioni in un altro campo.


22

Nota che i ()caratteri di stripping non funzionano per uno stile di scrittura dei numeri del Regno Unito che è comune: il +44 (0) 1234 567890che significa comporre il numero internazionale:
+441234567890
o nel quadrante del Regno Unito01234567890


15

Hai dato un'occhiata a RegExLib ?

L'immissione del numero di telefono negli Stati Uniti ha riportato un bel elenco di possibilità.


3
Sembra un ottimo modo per integrare bug oscuri nel tuo codice.
Tom Lord,

12

Il mio tentativo di regex senza restrizioni:

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

accetta:

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

Rejects:

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

Sta a te disinfettarlo per la visualizzazione. Dopo la convalida potrebbe essere un numero però.


12

Ho trovato che funziona abbastanza bene:

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

Funziona con questi formati numerici:

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

Assicurati di usare flag globali E multilinea per assicurarti.

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


11

Se stai parlando della convalida del modulo, la regexp per convalidare il significato corretto così come i dati corretti sarà estremamente complessa a causa delle diverse norme nazionali e dei fornitori. Sarà anche difficile tenersi aggiornati.

Interpreto la domanda come alla ricerca di un modello ampiamente valido, che potrebbe non essere coerente internamente - ad esempio avere un set di numeri valido, ma non convalidare che la linea principale, lo scambio, ecc. Al modello valido per il prefisso del prefisso del paese .

Il Nord America è semplice e per gli internazionali preferisco usare un modello "idiomatico" che copre i modi in cui le persone specificano e ricordano i loro numeri:

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

Il modello nordamericano si assicura che se una parentesi è inclusa entrambe sono. I conti internazionali per un '+' iniziale opzionale e il prefisso internazionale. Dopo quello, sei nel linguaggio. Le corrispondenze valide sarebbero:

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

Ciò può essere di parte poiché la mia esperienza è limitata al Nord America, all'Europa e ad un po 'di Asia.


Ho cercato di implementare quanto sopra nel mio script di convalida javascript ma continuo a ricevere un invalid quantifiererrore. Qualche idea su cosa sto facendo di sbagliato?
Jannis,

Aggiungerei il banale caso in cui il telefono è specificato senza simboli ma forse spazi e prefisso internazionale, in Europa è tipico per i numeri locali e mobili: 676412342, 676 46 32 12, 676 463 212
rupps

11

Ecco un modello meraviglioso che si avvicinava di più alla convalida che dovevo raggiungere. Non sono l'autore originale, ma penso che valga la pena condividerlo poiché ho riscontrato che questo problema è molto complesso e senza una risposta concisa o ampiamente utile.

Il seguente regex rileverà combinazioni di numeri e caratteri ampiamente utilizzate in una varietà di formati di numeri di telefono globali:

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

Fonte originale: http://www.regexr.com/38pvb


Questo ha un supporto limitato per le estensioni. Corrisponde a "616-555-1234 x567" ma non a "616-555-1234 ext. 567".
Jon Schneider,

2
Falso positivo per es. "------- (((((((((55555555" o "9999999999999999999999999"
mikep

Non convalida il numero di macdonald di Nitherland +31 76 596 4192 (stavo solo testando numeri casuali)
BIOHAZARD

10

Il mio istinto è rafforzato dalla quantità di risposte a questo argomento: esiste un numero praticamente infinito di soluzioni a questo problema, nessuna delle quali sarà elegante.

Onestamente, consiglierei di non provare a convalidare i numeri di telefono. Anche se potessi scrivere un validatore grande e peloso che consentirebbe tutti i diversi formati legittimi, finirebbe per consentire praticamente qualsiasi cosa che assomigli in remoto a un numero di telefono, in primo luogo.

Secondo me, la soluzione più elegante è quella di convalidare una lunghezza minima, niente di più.


Dopo aver provato alcuni di questi e aver esaminato i dati esistenti e il feedback degli utenti, tenderei ad essere d'accordo ...
Christopher King,

A volte è necessario eseguire la convalida. Se invio codici di conferma, non posso semplicemente inviare un codice a qualsiasi immondizia casuale che uno spammer ha inserito nel campo. Voglio assicurarmi che il numero sia probabilmente un numero di telefono prima di sprecare risorse per inviarlo.
Luca,

10

Questo è un semplice schema di espressioni regolari per i numeri di telefono filippini:

((\+[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}

corrisponderà a questi:

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

Il primo corrisponderà a QUALSIASI codice paese a due cifre, mentre il secondo corrisponderà esclusivamente al codice paese filippino.

Provalo qui: http://refiddle.com/1ox


Grazie. Che ne dici di numeri di rete fissa con prefisso come 028231234? Mi chiedo se i prefissi sono solo numeri di 2-3 cifre e sono sempre preceduti da 0?
Stormwild,

9

Ecco il mio miglior tentativo finora. Gestisce i formati sopra, ma sono sicuro che mi mancano alcuni altri formati possibili.

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

9

Avrai difficoltà a gestire i numeri internazionali con una regex singola / semplice, vedi questo post sulle difficoltà dei numeri di telefono internazionali (e persino nordamericani).

Ti consigliamo di analizzare le prime cifre per determinare qual è il codice paese, quindi agire in modo diverso in base al paese.

Oltre a ciò - l'elenco che hai fornito non include un altro formato statunitense comune - tralasciando l'iniziale 1. La maggior parte dei telefoni cellulari negli Stati Uniti non lo richiede e inizierà a confondere le generazioni più giovani a meno che non abbiano composto un numero internazionale.

Hai correttamente identificato che si tratta di un problema difficile ...

-Adamo


Non è una soluzione offerta. È POSSIBILE. Solo perché è complicato o complesso non significa che dovresti solo alzare le braccia.
Eric Hodonsky,

7

Dopo aver letto queste risposte, sembra che non ci sia un'espressione regolare semplice che può analizzare un mucchio di testo ed estrarre numeri di telefono in qualsiasi formato (incluso quello internazionale con e senza il segno più).

Ecco cosa ho usato di recente per un progetto client, in cui abbiamo dovuto convertire tutti i numeri di telefono in qualsiasi formato in tel: links.

Finora, ha funzionato con tutto ciò che ci hanno lanciato, ma se si verificano errori, aggiornerò questa risposta.

regex:

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

Funzione PHP per sostituire tutti i numeri di telefono con tel: links (nel caso qualcuno fosse curioso):

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

Questa espressione regolare corrisponde +1 1234562222222222222222222222.
Varda Elentári,

perché non semplicemente tornare?
thexande

Falso positivo per "99999999999999999999999999999999999999999"
Ben Wheeler

6

Credo che i moduli Perl di Number :: Phone :: US e Regexp :: Common (in particolare la fonte di Regexp :: Common :: URI :: RFC2806 ) possano aiutare.

La domanda dovrebbe probabilmente essere specificata in modo un po 'più dettagliato per spiegare lo scopo della validazione dei numeri. Ad esempio, 911 è un numero valido negli Stati Uniti, ma 911x non è per alcun valore di x. Questo è così che la compagnia telefonica può calcolare quando hai finito di chiamare. Esistono diverse varianti su questo problema. Ma il tuo regex non controlla la parte del prefisso, quindi non sembra essere un problema.

Come la convalida degli indirizzi e-mail, anche se hai un risultato valido non puoi sapere se è stato assegnato a qualcuno fino a quando non lo provi.

Se stai provando a convalidare l'input dell'utente, perché non normalizzare il risultato e farlo con esso? Se l'utente inserisce un numero che non è possibile riconoscere come un numero valido, salvarlo come immesso o eliminare i caratteri non disponibili. Il modulo Number :: Phone :: Normalize Perl potrebbe essere fonte di ispirazione.


Ho intenzione di uscire su un arto qui e dire che consentire il 911 come numero di telefono è probabilmente una cattiva idea in quasi tutte le applicazioni di questa regex. Buona cattura però.
Nicholas Flynt,

4

Lavoro per una società di ricerche di mercato e dobbiamo filtrare questi tipi di input per tutto il tempo. Lo stai complicando troppo. Basta rimuovere i caratteri non alfanumerici e vedere se c'è un'estensione.

Per ulteriori analisi è possibile abbonarsi a uno dei numerosi provider che ti darà accesso a un database di numeri validi e ti dirà se sono fissi o mobili, disconnessi, ecc. Costa denaro.


Convalida? 123% $) *% () $ * () # 456 * () * $ # (* (# $ @ 8908 corrisponderebbe alla soluzione proposta.
PlexQ

1
@PlexQ 555-123-1234, 07777777777, 90210, 01/01/1901 - gli utenti sono inventivi nella sperimentazione di rifiuti attraverso la convalida. Meglio non mettere a tacere quelli che hanno davvero dei dati strani usando una convalida eccessivamente restrittiva e dicendo loro che si sbagliano.
ReactiveRaven il

4

Sostituisci i caratteri di formattazione, quindi controlla la validità del telefono rimanente. In PHP,

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

Rompere una regexp complessa come questa può essere altrettanto efficace, ma molto più semplice.


3

Ho trovato questo qualcosa di interessante. Non l'ho provato ma sembra che funzioni

<?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.';
}
?>

4
Il tuo messaggio sembra indicare che non hai scritto questo codice. Ti dispiacerebbe citare una fonte, per favore?
Alastair Irvine,


3

Probabilmente sarebbe meglio usare un input mascherato per questo. In questo modo gli utenti possono inserire SOLO numeri e formattare come meglio credi. Non sono sicuro se questo sia per un'applicazione web, ma se lo è c'è un plugin jQuery molto click che offre alcune opzioni per farlo.

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

Esaminano anche come mascherare gli input dei numeri di telefono nel loro tutorial.


3

Eccone uno che funziona bene in JavaScript. È in una stringa perché è quello che si aspettava il widget Dojo.

Corrisponde a un numero NANP del Nord America a 10 cifre con estensione opzionale. Spazi, trattini e punti sono delimitatori accettati.

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

3

Stavo lottando con lo stesso problema, cercando di rendere la mia candidatura a prova di futuro, ma questi ragazzi mi hanno portato nella giusta direzione. In realtà non sto controllando il numero stesso per vedere se funziona o no, sto solo cercando di assicurarmi che sia stata inserita una serie di numeri che potrebbero avere o meno un'estensione.

Nel peggiore dei casi, se l'utente dovesse estrarre un numero non formattato dal file XML, digiterebbe comunque i numeri nel tastierino numerico del telefono 012345678x5, senza una vera ragione per mantenerlo carino. Quel tipo di RegEx sarebbe uscito qualcosa di simile per me:

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

2

La mia inclinazione è quella di concordare sul fatto che spogliarsi senza cifre e accettare semplicemente ciò che c'è di meglio. Forse per assicurare che siano presenti almeno un paio di cifre, sebbene ciò proibisca qualcosa come un numero di telefono alfabetico "ASK-JAKE" per esempio.

Un paio di semplici espressioni perl potrebbero essere:

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

Usa il primo per tenere uniti i gruppi di cifre, il che potrebbe fornire indizi di formattazione. Usa il secondo per lanciare banalmente tutte le non cifre.

È preoccupante che potrebbe essere necessario fare una pausa e inserire più chiavi? O qualcosa del tipo 555-1212 (attendere il segnale acustico) 123?


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

Deve terminare con una cifra, può iniziare con (o + o una cifra e può contenere + - (o)


2

Per chiunque sia interessato a fare qualcosa di simile con i numeri di cellulare irlandesi, ecco un modo semplice per realizzarlo:

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

C'è anche una soluzione JQuery su quel link.

MODIFICARE:

soluzione 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();
});


});

Fonte .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.