regulärer Ausdruck für Telefonnummer

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Hallo zusammen,

ich komme nicht weiter und wollte mal fragen, ob mir jemand weiterhelfen kann. Ich möchte die Eingabe einer Telefonnummer mit einem regulären Ausdruck überprüfen.

Folgende Schreibweisen sind in z. B. Ordnung:
+49 1225 56650
+49 122556650
+49 1225 5665-0

Leerzeichen dürfen öfter vorkommen, jedoch nicht mehrmals hintereinander.
Der Bindestrich darf nur einmal vorkommen.

Code: Alles auswählen

import re

telefonnummer = "+49 1225 5665-0"
telefonmuster = r"[+][0-9][0-9][ ][0-9\s-]*"

if (re.fullmatch(telefonmuster, telefonnummer)):
    print(True)
else:
    print(False)
Nach diesem regulären Ausdruck sind beide oben beschriebenen Bedingungen nicht erfüllt.

Wie kann ich das ändern?

Viele Grüße

snowflake
Benutzeravatar
pillmuncher
User
Beiträge: 1485
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Falls das keine Übungasaufgabe ist: nimm lieber https://pypi.org/project/phonenumbers.

Guckstu:

Code: Alles auswählen

>>> import phonenumbers as pns
>>> pns.parse('+49 1225 56650')
PhoneNumber(country_code=49, national_number=122556650, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=0, preferred_domestic_carrier_code=None)
>>> pns.parse('+49 122556650')
PhoneNumber(country_code=49, national_number=122556650, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=0, preferred_domestic_carrier_code=None)
>>> pns.parse('+49 1225 5665-0')
PhoneNumber(country_code=49, national_number=122556650, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=0, preferred_domestic_carrier_code=None)
Ich bin mir nicht sicher, ob man Telefonnummern überhaupt mit regex parsen kann. Dafür gibt es im internationalen Telefonnummernsystem zuviele Ausnahmen und Sonderregelungen. In den meisten Ländern fällt zB. die führende Null weg und wird durch +<Ländercode> ersetzt, in Italien bleibt die Null aber bestehen - aus 0123456789 würde dann +390123456789, nicht +39123456789. Klar ist das kein Problem, wenn man nur deutsche Nummern verarbeiten will, aber a) wird einem das ziemlich bald auf die Füße fallen und b) warum dann überhaupt eine Ländervorwahl? Siehe auch: Falsehoods Programmers Believe About Phone Numbers
In specifications, Murphy's Law supersedes Ohm's.
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Hallo pillmuncher,

das ist keine Übung. Ich möchte dies für meine Kontaktverwaltung nutzen. Eigentlich sollten die Telefonnummern der DIN 5008 entsprechen. Die angeführten Beispiele sind so aufgebaut.

Ich bekomme es nicht hin. Vielen Dank.

snowflake
Sirius3
User
Beiträge: 17793
Registriert: Sonntag 21. Oktober 2012, 17:20

@snowflake: die Grundlagen der regulären Ausdrücke kann und will Dir hier niemand abtippen, dafür gibt es genug Quellen im Internet.
Was Du Dir anschauen solltest, sind optionale Zeichen und Gruppierung.
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Hallo Sirius3,

es geht mir nicht darum, dass mir jemand die Grundlagen beibringt, sondern wie ich überprüfen kann, ob ein Zeichnen nur einmal vorhanden ist bzw. ein Leerzeichen nicht von einem weiteren Leerzeichen gefolgt wird. In den Quellen im Internet habe ich nichts für mich verwertbares gefunden, um mein Problem zu lösen. Mit den Gruppen (Klammern) habe ich schon versucht, bin aber zu keinem Ergebnis gekommen, was mein Problem löst. Das von mir geschrieben Skript funktioniert halt nur bedingt.Trotzdem vielen Dank.

Viele Grüße

snowflake
Sirius3
User
Beiträge: 17793
Registriert: Sonntag 21. Oktober 2012, 17:20

Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@snowflake

ich nutze zum Prüfen von RegEx ab und an das hier
https://regex101.com/
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

@Buchfink: Vielen Dank für den Hinweis. Das schaue ich mir an.
Benutzeravatar
pillmuncher
User
Beiträge: 1485
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@snowflake: Ich hab dir doch die phonenumbers-Bibliothek empfohlen und sogar verlinkt. Warum probierst du es nicht einfach mal damit, statt die mit irgendwelchem regex-Gebastel irgendwas Halbgares zusammen zu stopseln? Zum Programmieren gehört auch, dass man weiß, wann man etwas nicht selbst programmieren sollte.

Im Übrigen: Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems. -- Jamie Zawinski
In specifications, Murphy's Law supersedes Ohm's.
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

@pillmuncher:
Entschuldige bitte, dass ich mich bzgl. der Bibliothek noch nicht zurück gemeldet habe. Morgen in der Früh werde ich die testen und hier auch eine Rückmeldung posten. Vielen Dank für Deine Unterstützung.

snowflake
Benutzeravatar
Lechim
User
Beiträge: 4
Registriert: Montag 7. Oktober 2013, 20:39
Wohnort: Berlin

Hier noch eine wie ich finde interessante Seite zu RegExs.
Zu 'Phone' gibt es alleine ~400 Treffer:

https://regexlib.com/Search.aspx?k=phon ... m=-1&ps=50.

Eventuell ist ja das passende Pattern dabei.
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Guten Morgen zusammen.

@pillmuncher: Die phonenumbers-Bibliothek habe ich wie folgt getestet:

Code: Alles auswählen

import phonenumbers
x = phonenumbers.parse("+442083661x177", "DE")
Nach print(x) erscheint folgende Meldung:
Country Code: 44 National Number: 2083661177
Der Buchstabe x wurde einfach weggelassen und somit wäre die Nummer korrekt.

Bei der Eingabe wie folgt wird True zurück geliefert und das darf eigentlich nicht sein. Vermutlich habe ich da irgendwo noch einen Fehler drin.

Code: Alles auswählen

phonenumbers.is_valid_number(x)

@Lechim: Die Seite ist wirklich sehr interessant und ich habe mir den Link auch gleich mal weg kopiert.

Auf folgender Seite wurde ich fündig: https://regexlib.com/RETester.aspx?regexp_id=2952

Regulärer Ausdruck: ^(((((((00|\+)49[ \-/]?)|0)[1-9][0-9]{1,4})[ \-/]?)|((((00|\+)49\()|\(0)[1-9][0-9]{1,4}\)[ \-/]?))[0-9]{1,7}([ \-/]?[0-9]{1,5})?)$

Ich verstehe den Ausdruck zwar nicht, aber er funktioniert und damit ist mein Problem gelöst. Die Lösung geht meiner Meinung nach über Grundlagen hinaus. Im Leben wäre ich nicht von alleine darauf gekommen.

Euch allen vielen Dank für die Unterstützung und

viele Grüße

snowflake
Benutzeravatar
pillmuncher
User
Beiträge: 1485
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@snowflake: Also bei mir kommt mit deinen Beispieldaten das richtige Ergebnis:

Code: Alles auswählen

>>> pns.is_valid_number(pns.parse("+442083661x177", "DE"))
False
In specifications, Murphy's Law supersedes Ohm's.
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

@pillmuncher: Jetzt wo ich Deine Lösung sehe, weiß ich, was ich falsch gemacht habe. Danke dafür.

Viele Grüße

snowflake
Benutzeravatar
__blackjack__
User
Beiträge: 13199
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snowflake: „Ich verstehe den Ausdruck zwar nicht, aber er funktioniert“ ist ja irgendwie nicht ganz konsistent. Du weisst nicht ob der wirklich funktioniert. Du hast nur noch kein Gegenbeispiel gefunden.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

@__Blackjack__: Anhand von Telefonnummern habe ich den regulären Ausdruck getestet. Ob ich jetzt wirklich alle Kombinationen nach DIN 5008 getestet habe, kann ich nicht mit Gewissheit sagen.
Benutzeravatar
__blackjack__
User
Beiträge: 13199
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snowflake: Na und auch nicht ob welche aus der noch grösseren Menge an Nummern die nicht DIN 5008 entsprechen, nicht vielleicht doch als valide erkannt werden, auch nicht.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

@__Blackjack__:
Na und auch nicht ob welche aus der noch grösseren Menge an Nummern die nicht DIN 5008 entsprechen, nicht vielleicht doch als valide erkannt werden, auch nicht.
Das ist richtig.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@snowflake
ich komme beruflich öfter (und zwangsläufig) mit RegEx (insb. auch mit komplexeren Ausdrücken) in Kontakt. Aber den obigen RegEx würde ich mangels Lesbarkeit eher nicht im Quellcode verwenden. (Guter Code ist leicht zu lesen)
Zumindest - so entnehme ich es Deinem Beitrag - du hier ja Wahlfreiheit hast :)
Da fände ich den Ansatz mit der Lib von @pillmuncher einfacher/lesbarer.

Um Gegenbeispiele (die nicht funktionieren) zu finden, kann ich als Tipp ^ und $ nennen. Diese Zeichen werden oft falsch gedeutet, da sie sich auf die Zeile und nicht auf einen gesamten Text beziehen. (Ich habe es nicht ausprobiert, aber bei zwei Telefonnummern, die durch einen Zeilenumbruch getrennt sind, könnten etwas "unerwartetes" heraus kommen. Mit dem Link von mir kannst Du das ja mal checken)

RegEx _können_ dann hilfreich sein, wenn man damit bestimmte Problemfälle aussortieren kann und dann z.B. eine performance-lastige DB-Abfrage sparen kann.

LG
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

@Buchfink: Vielen Dank für Deinen ausführlichen und sehr hilfreichen Kommentar. Der Ansatz von @pillmulcher hat einen gewissen Charme, weil er wie Du beschrieben hast, tatsächlich einfacher zu lesen ist. Ich werde das mit den Gegenbeispielen testen und bin gespannt, was dabei raus kommt.

Nochmals vielen Dank und viele Grüße

snowflake
Antworten