Regex für Zahlen, Telefonnummern und IP-Adressen

Muster zum Kopieren für Zahleneingaben, Telefonnummern und IP-Adressen, jedes getestet, mit Hinweisen, wo ein Parser oder eine Bibliothek die Aufgabe besser erledigt.

Direkt ausprobieren: Regex-Tester

Zahlen, Telefonnummern und IP-Adressen wirken wie leichte Ziele für einen Regex, weil sie überwiegend aus Ziffern bestehen. Jedes davon hat aber eine Falle: \d bedeutet in verschiedenen Sprachen Verschiedenes, Telefonnummern folgen nationalen Regeln, die kein Muster abbilden kann, und eine IP-Adresse ist nur gültig, wenn jeder Teil im erlaubten Bereich liegt. Die folgenden Muster wurden in Node.js getestet, sofern keine andere Engine genannt ist, und jedes Beispiel für eine akzeptierte oder abgelehnte Eingabe haben wir tatsächlich ausgeführt.

Nur Zahlen

ZielMusterAkzeptiertLehnt ab
Nur Ziffern^[0-9]+$123, 007-42, 3.14, ein führendes Leerzeichen, leere Eingabe
Ganzzahl, optionales Vorzeichen^[+-]?[0-9]+$-42, +42, 0073.14, 1e3
Ganzzahl ohne führende Nullen^-?(?:0|[1-9][0-9]*)$0, -42007, +42
Dezimalzahl (mit Punkt)^[+-]?(?:[0-9]+(?:\.[0-9]+)?|\.[0-9]+)$3.14, -0.5, .55., 1e3, 1,000
Zahl im JSON-Stil^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$1.5E-7, -0.5, 01.5, +42
Tausendertrennzeichen (Komma)^[0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]+)?$1,000, 12,345,678.90, 1001000, 1,00

Ein Regex prüft die Form, nicht den Wert. Für einen Bereich wie 1 bis 100 prüfen Sie die Ziffern und vergleichen die Zahl anschließend im Code. Lassen Sie den Regex aber nicht weg, um sich allein auf die Umwandlung zu verlassen: In JavaScript ergibt Number('') den Wert 0, Number(' 42 ') den Wert 42, Number('0x1A') den Wert 26 und parseInt('12abc') den Wert 12.

Trifft \d nur 0 bis 9?

Nicht überall. Wir haben ^\d+$ gegen die arabisch-indischen Ziffern ٣٤ getestet:

EngineNicht-ASCII-Ziffern getroffen?Auf 0–9 beschränken
JavaScriptNein, auch nicht mit dem Flag uNicht nötig; \p{Nd} mit u trifft alle Dezimalziffern
Python 3 (str-Muster)Ja, auch vollbreite Ziffern wie 12[0-9] oder das Flag re.ASCII
PHP (PCRE)Nein; mit dem Modifikator u ja[0-9]
.NETJa[0-9] oder RegexOptions.ECMAScript
Perl 5Ja[0-9] oder der Modifikator /a

Das wird relevant, wenn ein Wert den Regex passiert und danach auf Code trifft, der ihn anders liest. Pythons int('٣٤') gibt 34 zurück, während eine Datenbankspalte oder ein anderer Dienst den Wert womöglich ablehnt. Schreiben Sie [0-9], wenn Sie ASCII-Ziffern meinen; das bedeutet in jeder Engine dasselbe.

Telefonnummern

Das einzige Format mit einer einfachen, internationalen Definition ist E.164: ein Pluszeichen, eine Ländervorwahl, die nicht mit 0 beginnt, und insgesamt höchstens 15 Ziffern.

^\+[1-9]\d{1,14}$     E.164, Pluszeichen Pflicht (am besten zum Speichern)
^\+?[1-9]\d{1,14}$    Pluszeichen optional

Mit Pflicht-Plus passen +14155552671 und +442071838750, während +0123456789, eine 16-stellige Nummer und 004914155552671 (mit dem internationalen Präfix 00 geschrieben) scheitern. Menschen tippen Leerzeichen, Punkte, Bindestriche und Klammern, entfernen Sie diese deshalb zuerst mit value.replace(/[\s().-]/g, ''); so wird aus +1 415 555 2671 die Nummer +14155552671.

Die Grenzen zeigen sich schnell. Das Muster prüft nur die Form, deshalb passt +12, obwohl keine echte Nummer so kurz ist. Schlimmer noch: +49 (0)30 1234567 wird nach dem Bereinigen zu +490301234567 und passt, ist aber die falsche Nummer. Die 0 in Klammern ist die nationale Verkehrsausscheidungsziffer, die beim Wählen aus dem Ausland wegfallen muss.

Nationale Formate sind nicht besser. Das verbreitete US-Muster ^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$ akzeptierte (415-555-2671 mit nicht geschlossener Klammer und 000-000-0000, das keine echte Nummer sein kann. Jedes Land hat eigene Längen, Präfixe und Mobilfunkbereiche, und die ändern sich. Für echte Validierung und Formatierung nehmen Sie Googles libphonenumber oder eine seiner Portierungen: libphonenumber-js für JavaScript, phonenumbers für Python, giggsey/libphonenumber-for-php für PHP. Speichern Sie das E.164-Ergebnis und bestätigen Sie per SMS-Code, dass die Nummer dem Nutzer gehört, wenn es darauf ankommt.

IPv4-Adressen

Die beliebte Abkürzung ^\d{1,3}(?:\.\d{1,3}){3}$ akzeptierte 256.1.1.1 und 999.999.999.999. Um jeden Teil auf 0–255 zu begrenzen, schreiben Sie die Bereiche aus:

^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$

Den Oktett-Teil haben wir gegen jede Zahl von 0 bis 999 geprüft, geschrieben mit einer, zwei und drei Ziffern, und das vollständige Muster gegen 200.000 zufällige Adressen; es stimmte jedes Mal mit net.isIPv4() von Node überein. Es akzeptiert 0.0.0.0, 192.168.1.1 und 255.255.255.255 und lehnt 192.168.1, 192.168.1.1.1 sowie führende Nullen wie in 192.168.01.1 ab.

Führende Nullen abzulehnen ist Absicht. Manche Parser lesen sie als Oktalzahl: Pythons socket.inet_aton('010.0.0.1') ergab bei uns die Adresse 8.0.0.1. net.isIPv4() in Node, ipaddress.ip_address() in Python und filter_var($ip, FILTER_VALIDATE_IP) in PHP lehnten 192.168.01.1 ebenfalls ab.

Um Adressen in einer Logzeile zu finden, lassen Sie ^ und $ weg, setzen \b auf beide Seiten und verwenden das Flag g. Bei from 10.0.0.5 to 192.168.1.300 via 8.8.8.8 lieferte das 10.0.0.5 und 8.8.8.8. Ohne \b erzeugte der Text 1192.168.1.300x einen falschen Treffer, nämlich 192.168.1.30. Eine Einschränkung bleibt: In 1.2.3.4.5 trifft auch die Variante mit \b noch 1.2.3.4.

IPv6-Adressen: Nehmen Sie einen Parser

IPv6 erlaubt :: als Ersatz für eine Folge von Null-Gruppen, optionale führende Nullen, eingebettetes IPv4 wie ::ffff:192.0.2.1 und Zonen-IDs wie fe80::1%eth0. Ein Regex für all das ist lang und leicht auf subtile Weise falsch. Ein Parser ist kürzer und besser getestet:

  • Node.js: net.isIPv6(value) oder net.isIP(value), das 4, 6 oder 0 zurückgibt. Beide akzeptierten eingebettetes IPv4 und Zonen-IDs.
  • Python: ipaddress.ip_address(value) wirft bei ungültigen Werten ValueError. Es akzeptierte eingebettetes IPv4 und Zonen-IDs.
  • PHP: filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6). Es akzeptierte eingebettetes IPv4, lehnte aber fe80::1%eth0 ab.
  • Browser: Einen eingebauten IP-Validator gibt es nicht, nehmen Sie deshalb eine Bibliothek wie ipaddr.js.

Brauchen Sie trotzdem einen Regex, etwa in einem Schema oder einer Konfigurationsdatei, die nur so etwas annimmt, deckt dieses 408 Zeichen lange Muster die hexadezimalen Formen ab und lehnt eingebettetes IPv4 und Zonen-IDs bewusst ab. Bei 500.000 generierten und mutierten Strings ohne Punkte oder Prozentzeichen stimmte es bei jedem einzelnen mit net.isIPv6() überein.

^(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:))$

Fehler, durch die ungültige Eingaben durchrutschen

  • Fehlende Anker. /\d+/.test('abc123') ist true, weil irgendwo Ziffern gefunden werden. Zur Validierung brauchen Sie ^ und $.
  • Alternation außerhalb einer Gruppe. ^cat|dog$ bedeutet „beginnt mit cat oder endet mit dog“ und traf deshalb cats and dogs!. Schreiben Sie ^(?:cat|dog)$.
  • Das Flag m. Damit passen ^ und $ an jeder Zeile, deshalb akzeptierte /^\d+$/m den zweizeiligen String "abc\n123". Verwenden Sie m nie, wenn Sie einen einzelnen Wert validieren.
  • $ vor einem abschließenden Zeilenumbruch. In Python, PHP und .NET akzeptierte ^\d+$ den Wert "42\n". Nehmen Sie re.fullmatch() in Python, den Modifikator D in PHP oder \z in PHP und .NET. JavaScript lehnte den Wert ab.
  • Das Flag g mit test(). Ein Regex mit g merkt sich lastIndex, deshalb lieferte /^\d+$/g.test('42'), dreimal auf demselben Objekt aufgerufen, true, false, true.
  • Nicht verankerte Alternativen in falscher Reihenfolge. Die Suche in 255.255.255.255 mit dem Oktett als (?:\d|1\d\d|2[0-4]\d|25[0-5]) traf nur 255.255.255.2, weil die Engine die erste passende Alternative nimmt. Stellen Sie längere Alternativen nach vorn oder verankern Sie das Muster.

Testen Sie Ihr Muster vor dem Einsatz

Fügen Sie ein Muster ohne Schrägstriche in den Regex-Tester ein, setzen Sie die Flags auf gm und tragen Sie Ihre Beispiele zeilenweise ein: gültige, ungültige und die unbequemen Fälle von dieser Seite. Jede passende Zeile wird hervorgehoben. Der Tester nutzt die JavaScript-Engine Ihres Browsers, prüfen Sie die oben beschriebenen Unterschiede bei \d und $ also erneut, wenn das Muster in Python, PHP oder .NET laufen soll. Sie wollen stattdessen E-Mail-Adressen validieren? Lesen Sie Regex für E-Mail-Validierung.

Häufige Fragen

Welches Regex-Muster erlaubt nur Zahlen?

Verwenden Sie ^[0-9]+$ für reine Ziffern oder ^[+-]?[0-9]+$, um ein Vorzeichen zuzulassen. Ziehen Sie [0-9] dem \d vor, denn in Python, .NET und PHP mit dem Modifikator u trifft \d auch Ziffern anderer Schriften.

Welches Regex-Muster validiert internationale Telefonnummern?

Für das E.164-Format ^\+[1-9]\d{1,14}$, nachdem Leerzeichen, Punkte, Bindestriche und Klammern entfernt wurden. Es prüft nur die Form; ob eine Nummer für ihr Land tatsächlich gültig ist, prüfen Sie mit libphonenumber oder einer seiner Portierungen.

Wie lautet das Regex-Muster für eine gültige IPv4-Adresse?

^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$ begrenzt jeden Teil auf 0 bis 255 und lehnt führende Nullen ab. Für IPv6 nehmen Sie einen Parser wie net.isIPv6 in Node.js oder ipaddress in Python.

Warum akzeptiert mein Regex Eingaben mit einem Zeilenumbruch am Ende?

In Python, PHP und .NET passt $ auch direkt vor einem abschließenden Zeilenumbruch. Verwenden Sie re.fullmatch in Python, den Modifikator D in PHP oder \z statt $.
Direkt ausprobieren: Regex-Tester