Frage Eine umfassende Regex für die Überprüfung der Telefonnummer


Ich versuche, eine umfassende Regex zu erstellen, um Telefonnummern zu überprüfen. Im Idealfall würde es mit internationalen Formaten umgehen, aber es muss mit US-Formaten umgehen, einschließlich der folgenden:

  • 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

Ich antworte mit meinem aktuellen Versuch, aber ich hoffe, dass jemand etwas besseres und / oder eleganteres hat.


824


Ursprung


Antworten:


Bessere Option ... streichen Sie einfach alle nicht-einstelligen Zeichen am Eingang (außer 'x' und führenden '+' Zeichen), vorsichtig wegen der britischen Tendenz, Zahlen in der Nicht-Standard-Form zu schreiben +44 (0) ... Wenn Sie aufgefordert werden, das internationale Präfix zu verwenden (in diesem speziellen Fall sollten Sie die (0) vollständig).

Dann haben Sie am Ende Werte wie:

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

Dann, wenn Sie anzeigen, formatieren Sie nach Herzenslust. z.B.

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

482



Es stellt sich heraus, dass es zumindest für Nordamerika, das so genannte NANP.

Sie müssen genau angeben, was Sie wollen. Was sind legale Trennzeichen? Leerzeichen, Bindestriche und Punkte? Kein Trennzeichen erlaubt? Kann man Trennzeichen (z. B. + 0,111-222,3333) mischen? Wie werden Erweiterungen (z. B. 111-222-3333 x 44444) gehandhabt? Was ist mit speziellen Zahlen, wie 911? Wird die Vorwahl optional oder erforderlich sein?

Hier ist eine Regex für eine 7 oder 10 stellige Zahl, mit Erweiterungen erlaubt, Trennzeichen sind Leerzeichen, Bindestriche oder Punkte:

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



.*

Wenn der Benutzer Ihnen seine Telefonnummer geben möchte, dann vertrauen Sie ihm, um es richtig zu machen. Wenn er es dir nicht geben will, dann wird er ihn entweder zwingen, eine gültige Nummer einzugeben, oder ihn dazu bringen, eine zufällige Zeichenfolge einzugeben, die zu deiner Regex passt. Ich könnte sogar versucht sein, die Nummer einer Premium-Rate-Sex-Linie nachzuschlagen und stattdessen diese einzugeben.

Ich würde auch einen der folgenden Punkte als gültige Einträge auf einer Website betrachten:

"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



Ich würde auch vorschlagen, die "Libphonummer"Google Bibliothek. Ich weiß, dass es keine Regex ist, aber es macht genau das, was Sie wollen.

Zum Beispiel wird es erkennen, dass:

15555555555

ist eine mögliche Nummer, aber keine gültige Nummer. Es unterstützt auch Länder außerhalb der USA.

Highlights der Funktionalität:

  • Parsen / Formatieren / Validieren von Telefonnummern für alle Länder / Regionen der Welt.
  • getNumberType - erhält den Typ der Nummer basierend auf der Nummer selbst; in der Lage, Festnetz-, Mobil-, gebührenfreie, Premium Rate-, Shared-Cost-, VoIP- und persönliche Nummern zu unterscheiden (wann immer möglich).
  • isNumberMatch - erhält ein Konfidenzniveau, ob zwei Zahlen gleich sein können.
  • getExampleNumber/getExampleNumberByType - bietet gültige Beispielnummern für alle Länder / Regionen, mit der Option anzugeben, welche Art von Beispieltelefonnummer benötigt wird.
  • isPossibleNumber - schnelles Erraten, ob eine Nummer eine mögliche Telefonnummer ist, indem nur die Längeninformationen verwendet werden, viel schneller als eine vollständige Validierung.
  • isValidNumber - Vollständige Bestätigung einer Telefonnummer für eine Region unter Verwendung von Längen- und Präfixinformationen.
  • AsYouTypeFormatter- Formatiert Telefonnummern im laufenden Betrieb, wenn Benutzer jede Ziffer eingeben.
  • findNumbers - findet Zahlen in der Texteingabe.
  • PhoneNumberOfflineGeocoder - bietet geografische Informationen zu einer Telefonnummer.

Beispiele

Das größte Problem bei der Telefonnummer-Validierung ist, dass es sehr kulturabhängig ist.

  • Amerika
    • (408) 974–2042 ist ein gültig US-Nummer
    • (999) 974–2042 ist kein gültiges US-Nummer
  • Australien
    • 0404 999 999 ist ein gültig Australische Nummer
    • (02) 9999 9999 ist auch ein gültig Australische Nummer
    • (09) 9999 9999 ist kein gültiges Australische Nummer

Ein regulärer Ausdruck ist in Ordnung, um das Format einer Telefonnummer zu überprüfen, aber es wird nicht wirklich in der Lage sein, das zu überprüfen Gültigkeit einer Telefonnummer.

Ich würde vorschlagen, einen einfachen regulären Ausdruck zu überspringen, um Ihre Telefonnummer zu testen und eine Bibliothek wie Google zu verwenden libphonenumber (Link zum GitHub-Projekt).

Einführung der Libphonummer!

Verwenden Sie eines Ihrer komplexeren Beispiele, 1-234-567-8901 x1234, du erhältst die folgenden Daten aus libphonenumber (Link zur Online-Demo):

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

So erfahren Sie nicht nur, ob die Telefonnummer gültig ist (was sie ist), sondern Sie erhalten auch eine konsistente Telefonnummernformatierung in Ihrem Gebietsschema.

Als Bonus, libphonenumber hat eine Reihe von Datensätzen, um auch die Gültigkeit von Telefonnummern zu überprüfen, also eine Zahl wie z +61299999999 (die internationale Version von (02) 9999 9999) gibt als gültige Zahl mit Formatierung zurück:

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

Libphonumber bietet Ihnen auch viele weitere Vorteile, z. B. das Abrufen des Ortes, an dem die Telefonnummer erkannt wurde, und das Abrufen der Zeitzoneninformationen aus der Telefonnummer:

PhoneNumberOfflineGeocoder Results
Location        Australia

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

Aber die ungültige australische Telefonnummer ((09) 9999 9999) gibt zurück, dass es keine gültige Telefonnummer ist.

Validation Results

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

Die Google-Version enthält Code für Java und Javascript, aber die Benutzer haben auch Bibliotheken für andere Sprachen implementiert, die das Google i18n-Telefonnummern-Dataset verwenden:

Wenn Sie nicht sicher sind, dass Sie immer Zahlen von einem Gebietsschema akzeptieren, und sie werden immer in einem Format sein, würde ich Ihnen dringend empfehlen, keinen eigenen Code dafür zu schreiben und Libphonummern für die Validierung und Anzeige von Telefonnummern zu verwenden.


128



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

Dies entspricht:

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

Auf $ n speichert es:

  1. Länderkennzeichen
  2. Telefonnummer
  3. Erweiterung

Sie können es testen https://www.regexpal.com/?fam=99127


65



Obwohl die Antwort, alle Whitespace zu entfernen, ordentlich ist, löst sie nicht wirklich das Problem, das gestellt wird, nämlich eine Regex zu finden. Nehmen Sie zum Beispiel mein Testskript, das eine Webseite herunterlädt und alle Telefonnummern mit der Regex extrahiert. Da du sowieso eine Regex brauchst, kannst du die Regex genauso gut erledigen. Ich kam auf Folgendes:

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

Hier ist ein Perl-Skript, um es zu testen. Wenn Sie übereinstimmen, enthält $ 1 die Ortsvorwahl, $ 2 und $ 3 die Telefonnummer und $ 5 die Nebenstelle. Mein Testskript lädt eine Datei aus dem Internet herunter und druckt alle Telefonnummern darin aus.

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

Bearbeiten:

Sie können \ W * zu \ s * \ W? \ S * in der Regex ändern, um es ein wenig zu straffen. Ich habe nicht an die Regex gedacht, etwa um Benutzereingaben in einem Formular zu überprüfen, als ich es geschrieben habe, aber diese Änderung macht es möglich, die Regex für diesen Zweck zu verwenden.

'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



Ich beantwortete diese Frage in einer anderen SO-Frage, bevor ich mich entschloss, auch meine Antwort als Antwort auf diesen Thread aufzunehmen, da sich niemand damit beschäftigte, wie man Elemente benötigte / nicht benötigte, indem man nur reguläre Ausdrücke ausgab: Regex funktioniert falsch, passt zu unerwarteten Dingen

Von meinem Beitrag auf dieser Website habe ich eine Kurzanleitung erstellt, die jedem helfen soll, seine eigene Regex für sein eigenes gewünschtes Telefonnummernformat zu erstellen, was ich (wie ich es auf der anderen Seite gemacht habe) vorwegnehmen würde, dass, wenn Sie zu restriktiv sind, Sie erhalten möglicherweise nicht die gewünschten Ergebnisse, und es gibt keine einheitliche Lösung, um alle möglichen Telefonnummern auf der Welt zu akzeptieren - nur das, was Sie als Format Ihrer Wahl akzeptieren. Benutzung auf eigene Gefahr.

Schneller Spickzettel

  • Starten Sie den Ausdruck: /^ 
  • Wenn Sie ein Leerzeichen benötigen, verwenden Sie: [\s] oder \s 
  • Wenn Sie Klammern benötigen, verwenden Sie: [(] und [)] . Verwenden \( und \) ist hässlich und kann Dinge verwirrend machen.
  • Wenn Sie möchten, dass etwas optional ist, setzen Sie a ? Danach
  • Wenn Sie einen Bindestrich möchten, geben Sie einfach ein - oder [-] . Wenn Sie es nicht als erstes oder letztes in einer Reihe von anderen Zeichen eingeben, müssen Sie es möglicherweise umgehen: \-
  • Wenn Sie verschiedene Optionen in einem Slot akzeptieren möchten, setzen Sie Klammern um die Optionen: [-.\s] erfordert einen Bindestrich, einen Punkt oder ein Leerzeichen. Ein Fragezeichen nach der letzten Klammer macht all diese Optionen für diesen Slot optional.
  • \d{3} : Benötigt eine 3-stellige Nummer: 000-999. Kurzschrift für [0-9][0-9][0-9].
  • [2-9] : Benötigt eine Ziffer 2-9 für diesen Slot.
  • (\+|1\s)? : Akzeptiere ein "Plus" oder eine 1 und ein Leerzeichen (Pipe-Zeichen, |, ist "oder") und macht es optional. Das "Plus" -Zeichen muss maskiert sein.
  • Wenn Sie möchten, dass bestimmte Nummern einem Slot entsprechen, geben Sie sie ein: [246] erfordert eine 2, 4 oder 6. [77|78] wird 77 oder 78 erfordern.
  • $/ : Beende den Ausdruck

38