Quale espressione regolare corrisponderà a numeri di telefono internazionali validi?


113

Devo determinare se un numero di telefono è valido prima di tentare di comporlo. La telefonata può arrivare ovunque nel mondo.

Quale espressione regolare corrisponderà a numeri di telefono internazionali validi?


In che modo le espressioni regolari gestiscono errori come i numeri fuori servizio? Prova a chiamare e gestisci il numero non valido come faresti con altri errori.

3
Sebbene tu abbia ragione sul fatto che la regex non può determinarlo, ogni tentativo in uscita consuma tempo e risorse. Fare un rapido controllo di integrità sul numero garantisce che una chiamata ovviamente fasulla non blocchi un canale prezioso.
Abtin Forouzandeh

1
LOL @ paxdiablo .... Immagino che 1-800-CALL-HELP supererà il test RegExp ... lol
Buhake Sindi

1
Qualcosa che non è chiaro in questa domanda è se i numeri devono essere validi se chiamati dagli Stati Uniti o da qualsiasi paese del mondo, perché la maggior parte delle soluzioni seguenti non convalida alcuni numeri validi (come 0030210 12312312 - un valido Numero greco chiamato da qualsiasi paese dell'UE)
Xeroxoid

1
@JonHanna Sono d'accordo su un punto, ma d'altra parte, dal punto di vista dell'UX non pensi che se un utente inserisce un numero 00XX ... X, il test dovrebbe passare? Ci sono casi in cui gli utenti (cioè le persone anziane) non sanno nemmeno cosa sia il + e come digitarlo su un tastierino numerico / telefonico. Inoltre potrei ancora sostenere che 00XXX è un numero internazionale valido (cioè nel contesto di un utente) dove invece del +, è stato utilizzato il codice di uscita.
Xeroxoid

Risposte:


96
\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|
2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|
4[987654310]|3[9643210]|2[70]|7|1)\d{1,14}$

È il formato corretto per la corrispondenza di un numero di telefono internazionale generico. Ho sostituito il codice di accesso internazionale incentrato sulla linea fissa degli Stati Uniti 011 con l'identificatore del codice di accesso internazionale standard "+", rendendolo obbligatorio. Ho anche cambiato il minimo per il numero nazionale ad almeno una cifra.

Tieni presente che se inserisci numeri in questo formato nella rubrica del tuo cellulare, puoi chiamare con successo qualsiasi numero nella tua rubrica, indipendentemente da dove ti trovi. Per le linee fisse, sostituire il segno più con il prefisso internazionale del paese da cui si sta componendo.

Si noti che questo NON tiene conto delle regole del piano numerico nazionale - in particolare, consente zeri e uno in posizioni che i piani numerici nazionali potrebbero non consentire e consente anche lunghezze dei numeri maggiori rispetto al piano numerico nazionale per alcuni paesi (ad esempio, gli Stati Uniti).


5
Mi sembra sensato.
Userò

17
Questo non è valido. I numeri di telefono europei possono iniziare con un doppio 0 senza un + all'inizio. Quindi un numero di telefono come: +44 8984 1234 (UK) è perfettamente valido anche se scritto 0044 8984 1234 che questa regexp (e anche su altre risposte) non supporta.
Xeroxoid

4
Combinato con i miglioramenti di @fezfox (?) E la lunghezza ottimizzata:^\+((?:9[679]|8[035789]|6[789]|5[90]|42|3[578]|2[1-689])|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)(?:\W*\d){0,13}\d$
SamWhan

1
+1. Dal punto di vista della UX, sì, potrebbe avere senso consentire 00di fronte. Dal punto di vista dello sviluppo e della manutenzione, direi che va benissimo applicare tutti i numeri per iniziare +o addirittura sostituirli 00con una +ogni volta che lo ottieni, soprattutto dato che la maggior parte delle persone è a conoscenza del +formato (che la maggior parte dei campi di input dei telefoni internazionali richiedono comunque). Inoltre è una soluzione di una riga e molto più leggibile. Questo approccio garantirebbe inoltre che tutti i numeri di telefono siano nello stesso formato e renderà la convalida molto meno soggetta a errori, rendendo così l'intera operazione più gestibile.
milosmns

1
Inoltre, nei "vecchi" giorni degli SMS pre-EDGE (GSM normale), l'utilizzo 00non inviava correttamente il messaggio, mentre iniziare con a +funzionava sempre a livello internazionale. Possiamo impazzire e renderlo super complesso, ma a volte è possibile / vale la pena eliminare alcuni vincoli per semplificarci la vita :)
milosmns

66

Tutti i codici paese sono definiti dall'ITU. La seguente regex si basa su ITU-T E.164 e sull'allegato al bollettino operativo ITU n. 930 - 15.IV.2009 . Contiene tutti i codici dei paesi correnti e i codici riservati per un utilizzo futuro. Anche se potrebbe essere accorciato un po ', ho deciso di includere ogni codice in modo indipendente.

Questo è per le chiamate provenienti dagli Stati Uniti. Per gli altri paesi, sostituire il codice di accesso internazionale (lo 011 all'inizio della regex) con quello appropriato per il piano di selezione di quel paese .

Inoltre, si noti che ITU E.164 definisce la lunghezza massima di un numero di telefono internazionale completo a 15 cifre. Ciò significa che un codice paese a tre cifre restituisce fino a 12 cifre aggiuntive e un codice paese a 1 cifra può contenere fino a 14 cifre aggiuntive. Quindi il

[0-9]{0,14}$

una fine della regex.

Ancora più importante, questa regex non significa che il numero sia valido: ogni paese definisce il proprio piano di numerazione interna. Ciò garantisce solo la validità del prefisso internazionale.

283 | 282 | 281 | 280 | 269 | 268 | 267 | 266 | 265 | 264 | 263 | 262 | 261 | 260 | 259 | 258 | 257 | 256 | 255 | 254 | 253 | 252 | 251 | 250 | 249 | 248 | 247 | 246 | 245 | 244 | 243 | 242 | 241 | 240 | 239 | 238 | 237 | 236 | 235 | 234 | 233 | 232 | 231 | 230 | 229 | 228 | 227 | 226 | 225 | 224 | 223 | 222 | 221 | 220 | 219 | 218 | 217 | 216 | 215 | 214 | 213 | 212 | 211 | 210 | 98 | 95 | 94 | 93 | 92 | 91 | 90 | 86 | 84 | 82 | 81 | 66 | 65 | 64 | 63 | 62 | 61 | 60 | 58 | 57 | 56 | 55 | 54 | 53 | 52 | 51 | 49 | 48 | 47 | 46 | 45 | 44 | 43 | 41 | 40 | 39 | 36 | 34 | 33 | 32 | 31 | 30 | 27 | 20 | 7 | 1) [0-9] {0, 14} $


12
Aveva quasi ragione ... "011" non fa parte di un codice internazionale. È proprio quello che le persone negli Stati Uniti devono comporre per effettuare una chiamata internazionale. Quel prefisso cambierà a seconda di dove si compone ... Quindi quel prefisso NON fa parte del numero.
Gabriel Magana

3
@gmagana - Lo menziono nella mia risposta (paragrafo 2)
Abtin Forouzandeh

1
Il punto è che non fa parte del numero di telefono. È come dire che il prefisso "1" per le chiamate interurbane nazionali degli Stati Uniti fa parte del numero di telefono.
Gabriel Magana

1
@gmagana - mentre hai ragione sul fatto che non fa parte del numero di telefono, è tecnicamente necessario per effettuare la chiamata.
Abtin Forouzandeh

2
@ Roger Pate: ho passato un po 'di tempo a capirlo e spero che possa essere utile ad altri. Speravo anche che qualcun altro potesse avere una soluzione migliore (motivo per cui non ho contrassegnato la mia risposta come accettata).
Abtin Forouzandeh

32

Questa è un'ulteriore ottimizzazione.

\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|
2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|
4[987654310]|3[9643210]|2[70]|7|1)
\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*(\d{1,2})$

(i) consente
di inserire prefissi internazionali validi (ii) seguiti da 9 o 10 cifre, con qualsiasi tipo o inserimento di delimitatori (eccetto tra le ultime due cifre)

Questo corrisponderà a:
+ 1-234-567-8901
+ 61-234-567-89-01
+ 46-234 5678901
+1 (234) 56
89901 +1 (234) 56-89 901
+46.234.567.8901
+1 / 234/567/8901


So che questa è una vecchia risposta, ma c'è qualche opzione per rendere l'1 opzionale per i numeri americani?
Adam Fratino

Quello che vuoi fare è (i) rendere il "+" opzionale e (ii) il codice internazionale opzionale. Quindi posto "?" dopo il + e dopo la prima parentesi chiusa.
fezfox

@ManosPasgiannis beh sì, come specificato "seguito da 9 o 10 cifre". Sembrerebbe che a cipro usi 8, quindi regola l'ultima sequenza rimuovendo una volta l'istanza di \ d \ W * e crea l'ultima espressione (\ d {1,3})
fezfox

22

Puoi utilizzare la libreria libphonenumber di Google.

PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
String decodedNumber = null;
PhoneNumber number;
    try {
        number = phoneNumberUtil.parse(encodedHeader, null);
        decodedNumber = phoneNumberUtil.format(number, PhoneNumberFormat.E164);
    } catch (NumberParseException e) {
        e.printStackTrace();
    }

2
Potrebbe essere una buona soluzione ma solo per controllare i numeri di telefono, prima di utilizzare questa libreria, devi importare un'enorme quantità di js ... perché libphonenumber.js ha bisogno della libreria di chiusura ... non è una soluzione leggera: /
J. BizMai

11

Questo funzionerà per i numeri internazionali;

C #:

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

JS:

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

11

Io uso questo:

/([0-9\s\-]{7,})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/

Vantaggi: riconosce gli inizi + o 011, lascia che sia lungo quanto necessario e gestisce molte convenzioni di estensione. (#, X, int, estensione)


Questo si avvicina molto alla maggior parte dei formati di numeri di telefono internazionali.
feeela

9

Ecco una versione "ottimizzata" della tua regex:

^011(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|
2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|
4[987654310]|3[9643210]|2[70]|7|1)\d{0,14}$

Puoi sostituire la \ds con [0-9]se la sintassi regex non supporta \d.



6

Modificata l'espressione regolare di @ Eric - aggiunto un elenco di tutti i codici paese (ottenuto da xxxdepy @ Github . Spero che lo troverai utile:

/(\+|00)(297|93|244|1264|358|355|376|971|54|374|1684|1268|61|43|994|257|32|229|226|880|359|973|1242|387|590|375|501|1441|591|55|1246|673|975|267|236|1|61|41|56|86|225|237|243|242|682|57|269|238|506|53|5999|61|1345|357|420|49|253|1767|45|1809|1829|1849|213|593|20|291|212|34|372|251|358|679|500|33|298|691|241|44|995|44|233|350|224|590|220|245|240|30|1473|299|502|594|1671|592|852|504|385|509|36|62|44|91|246|353|98|964|354|972|39|1876|44|962|81|76|77|254|996|855|686|1869|82|383|965|856|961|231|218|1758|423|94|266|370|352|371|853|590|212|377|373|261|960|52|692|389|223|356|95|382|976|1670|258|222|1664|596|230|265|60|262|264|687|227|672|234|505|683|31|47|977|674|64|968|92|507|64|51|63|680|675|48|1787|1939|850|351|595|970|689|974|262|40|7|250|966|249|221|65|500|4779|677|232|503|378|252|508|381|211|239|597|421|386|46|268|1721|248|963|1649|235|228|66|992|690|993|670|676|1868|216|90|688|886|255|256|380|598|1|998|3906698|379|1784|58|1284|1340|84|678|681|685|967|27|260|263)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{4,20}$/

Funziona come un fascino. Anche per i numeri di telefono olandesi. Grazie!
mauvm

2

C'è ovviamente una moltitudine di modi per farlo, come evidenziato da tutte le diverse risposte date finora, ma butto qui il mio valore di $ 0,02 e fornisco la regex di seguito, che è un po 'più concisa di quasi tutte le precedenti , ma anche più approfondito della maggior parte. Ha anche il piacevole effetto collaterale di lasciare il prefisso internazionale in $ 1 e il numero locale in $ 2.

^ \ + (? = \ D {5,15} $) (1 | 2 [078] | 3 [0-469] | 4 [013-9] | 5 [1-8] | 6 [0-6] | 7 | 8 [1-469] | 9 [0-58] | [2-9] ..) (\ d +) $


2

Nessuna critica riguardo a queste ottime risposte, voglio solo presentare la semplice soluzione che utilizzo per i nostri creatori di contenuti di amministrazione:

^(\+|00)[1-9][0-9 \-\(\)\.]{7,}$

Forza l'inizio con un più o due zeri e usa almeno un po 'di numeri, spazi bianchi, parentesi graffe, meno e il punto è facoltativo e nessun altro carattere. Puoi rimuovere in sicurezza tutti i non numeri e usarli in un tel: input. I numeri avranno una forma comune di rappresentazione e non devo preoccuparmi di essere restrittivo.


1

Una versione semplice per numeri europei, che corrisponde a numeri come 0034617393211 ma anche a numeri lunghi come 004401484172842.

^0{2}[0-9]{11,}

Spero che sia d'aiuto :·)


1
public static boolean validateInternationalPhoneNumberFormat(String phone) {
    StringBuilder sb = new StringBuilder(200);

    // Country code
    sb.append("^(\\+{1}[\\d]{1,3})?");

    // Area code, with or without parentheses
    sb.append("([\\s])?(([\\(]{1}[\\d]{2,3}[\\)]{1}[\\s]?)|([\\d]{2,3}[\\s]?))?");

    // Phone number separator can be "-", "." or " "

    // Minimum of 5 digits (for fixed line phones in Solomon Islands)
    sb.append("\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?\\d[\\-\\.\\s]?");

    // 4 more optional digits
    sb.append("\\d?[\\-\\.\\s]?\\d?[\\-\\.\\s]?\\d?[\\-\\.\\s]?\\d?$");

    return Pattern.compile(sb.toString()).matcher(phone).find();
}

1
Sebbene questo frammento di codice possa rispondere alla domanda, non fornisce alcun contesto per spiegare come o perché. Considera l'idea di aggiungere una o due frasi per spiegare la tua risposta.
brandonscript

1

Ecco una regex per i seguenti scenari di numeri di telefono più comuni. Sebbene questo sia adattato dal punto di vista degli Stati Uniti per i codici di zona, funziona per gli scenari internazionali.

  1. Il numero effettivo dovrebbe essere composto solo da 10 cifre.
  2. Per i numeri degli Stati Uniti il ​​prefisso può essere racchiuso tra parentesi ().
  3. Il codice del paese può contenere da 1 a 3 cifre. Facoltativamente può essere preceduto da un segno +.
  4. Possono essere presenti trattini, spazi, punti o nessuno spazio tra il prefisso del paese, il prefisso locale e il resto del numero.
  5. Un numero di telefono valido non può essere composto da tutti zeri.

    ^(?!\b(0)\1+\b)(\+?\d{1,3}[. -]?)?\(?\d{3}\)?([. -]?)\d{3}\3\d{4}$

Spiegazione:

    ^ - start of expression  
    (?!\b(0)\1+\b) - (?!)Negative Look ahead. \b - word boundary around a '0' character. \1 backtrack to previous capturing group (zero). Basically don't match all zeros.  
    (\+?\d{1,3}[. -]?)? - '\+?' plus sign before country code is optional.\d{1,3} - country code can be 1 to 3 digits long. '[. -]?' - spaces,dots and dashes are optional. The last question mark is to make country code optional.  
    \(?\d{3}\)? - '\)?' is to make parentheses optional. \d{3} - match 3 digit area code.  
    ([. -]?) - optional space, dash or dot
    $ - end of expression

Altri esempi e spiegazioni: https://regex101.com/r/hTH8Ct/2/


1

Ho usato questo di seguito:

^(\+|00)[0-9]{1,3}[0-9]{4,14}(?:x.+)?$

Il formato + CCC.NNNNNNNNNNxEEEE o 00CCC.NNNNNNNNNNxEEEE

Il numero di telefono deve iniziare con "+" o "00" per una chiamata internazionale. dove C è il prefisso internazionale di 1-3 cifre,

N è composto da un massimo di 14 cifre,

ed E è l'estensione (opzionale).

Il segno più iniziale e il punto che segue il prefisso internazionale sono obbligatori. Il carattere letterale "x" è richiesto solo se viene fornita un'estensione.



0

Il piano di numerazione internazionale si basa sul piano di numerazione ITU E.164 . Immagino che sia il punto di partenza della tua espressione regolare.

Lo aggiornerò se riesco a creare un'espressione regolare basata sulla numerazione ITU E.164.


0

Questa espressione Regex funziona per i numeri di telefono di India, Canada, Europa, Nuova Zelanda, Australia, Stati Uniti, insieme ai rispettivi codici paese:

"^(\+(([0-9]){1,2})[-.])?((((([0-9]){2,3})[-.]){1,2}([0-9]{4,10}))|([0-9]{10}))$"


0

Questo funziona per me, senza il prefisso 00, 001, 0011 ecc.

/^\+*(\d{3})*[0-9,\-]{8,}/



0

Ho creato la regexp per i numeri di telefono europei ed è specifica per il prefisso di composizione rispetto alla lunghezza del numero.

const PhoneEuropeRegExp = () => {
    // eu phones map https://en.wikipedia.org/wiki/Telephone_numbers_in_Europe
    const phonesMap = {
        "43": [4, 13],
        "32": [8, 10],
        "359": [7, 9],
        "385": [8, 9],
        "357": 8,
        "420": 9,
        "45": 8,
        "372": 7,
        "358": [5, 12],
        "33": 9,
        "350": 8,
        "49": [3, 12],
        "30": 10,
        "36": [8, 9],
        "354": [7, 9],
        "353": [7, 9],
        "39": [6, 12],
        "371": 8,
        "423": [7, 12],
        "370": 8,
        "352": 8,
        "356": 8,
        "31": 9,
        "47": [4, 12],
        "48": 9,
        "351": 9,
        "40": 9,
        "421": 9,
        "386": 8,
        "34": 9,
        "46": [6, 9],
    };
    const regExpBuilt = Object.keys(phonesMap)
        .reduce(function(prev, key) {
            const val = phonesMap[key];
            if (Array.isArray(val)) {
                prev.push("(\\+" + key + `[0-9]\{${val[0]},${val[1]}\})`);
            } else {
                prev.push("(\\+" + key + `[0-9]\{${val}\})`);
            }
            return prev;
        }, [])
        .join("|");
    return new RegExp(`^(${regExpBuilt})$`);
};

alert(PhoneEuropeRegExp().test("+420123456789"))

-4

Prova questo, non so se c'è un numero di telefono più lungo di 12:

^(00|\+){1}\d{12}$

1
Questo corrisponde a numeri che hanno esattamente 12 cifre incluso il prefisso internazionale. Questo è sbagliato perché non tiene conto della variabilità della lunghezza nel mondo. Inoltre, la lunghezza massima è in realtà di 15 cifre .
tmt

1
@tmt E ^(00|\+){1}\d{12,15}$allora?
turingtested il
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.