406 Stimmen

Regulärer Ausdruck für DNS-Hostname oder IP-Adresse?

Hat jemand einen regulären Ausdruck zur Hand, der auf jeden legalen DNS-Hostnamen oder jede IP-Adresse passt?

Es ist einfach, ein Programm zu schreiben, das in 95 % der Fälle funktioniert, aber ich hoffe, dass ich etwas bekomme, das gut getestet ist und genau den neuesten RFC-Spezifikationen für DNS-Hostnamen entspricht.

586voto

Jorge Ferreira Punkte 92489

Sie können die folgenden regulären Ausdrücke einzeln verwenden oder sie in einem gemeinsamen OR-Ausdruck kombinieren.

ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";

ValidHostnameRegex = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$";

ValidIpAddressRegex stimmt mit gültigen IP-Adressen überein und ValidHostnameRegex gültige Hostnamen. Je nach der von Ihnen verwendeten Sprache muss \ möglicherweise mit \.


ValidHostnameRegex ist gültig gemäß RFC 1123 . Ursprünglich, RFC 952 festgelegt, dass Hostnamen-Segmente nicht mit einer Ziffer beginnen dürfen.

http://en.wikipedia.org/wiki/Hostname

Die ursprüngliche Spezifikation von Hostnamen in RFC 952 , vorgeschrieben, dass Etiketten nicht starten dürfen mit einer Ziffer oder einem Bindestrich beginnen und nicht mit einem Bindestrich enden dürfen. Allerdings darf ein spätere Spezifikation ( RFC 1123 ) erlaubte Hostnamenbezeichnungen, die mit mit Ziffern beginnen.

Valid952HostnameRegex = "^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$";

74voto

Die Hostnamen-Regex von smink die Begrenzung der Länge der einzelnen Bezeichnungen innerhalb eines Hostnamens nicht beachtet. Jedes Label innerhalb eines gültigen Hostnamens darf nicht länger als 63 Oktette sein.

ValidHostnameRegex="^(\[a-zA-Z0-9\]|\[a-zA-Z0-9\]\[a-zA-Z0-9\\-\]{0,61}\[a-zA-Z0-9\])\\
(\\.(\[a-zA-Z0-9\]|\[a-zA-Z0-9\]\[a-zA-Z0-9\\-\]{0,61}\[a-zA-Z0-9\]))\*$"

Beachten Sie, dass der Backslash am Ende der ersten Zeile (oben) die Unix-Shell-Syntax zum Aufteilen der langen Zeile ist. Er ist nicht Teil des regulären Ausdrucks selbst.

Hier ist nur der reguläre Ausdruck allein in einer einzigen Zeile:

^(\[a-zA-Z0-9\]|\[a-zA-Z0-9\]\[a-zA-Z0-9\\-\]{0,61}\[a-zA-Z0-9\])(\\.(\[a-zA-Z0-9\]|\[a-zA-Z0-9\]\[a-zA-Z0-9\\-\]{0,61}\[a-zA-Z0-9\]))\*$

Sie sollten auch separat prüfen, ob die Gesamtlänge des Hostnamens darf 255 Zeichen nicht überschreiten . Weitere Informationen finden Sie in RFC-952 und RFC-1123.

35voto

Alban Punkte 2886

Zum Abgleich mit einer gültigen IP-Adresse verwenden Sie die folgende Regex:

(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}

anstelle von:

([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\.([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])){3}

Erläuterung

Viele Regex-Engines passen auf die erste Möglichkeit in der OR Reihenfolge. Versuchen Sie zum Beispiel die folgende Regex:

10.48.0.200

Test

Testen Sie den Unterschied zwischen gut gegen schlecht

6voto

Alex Volkov Punkte 2514

Ich scheine den oberen Beitrag nicht bearbeiten zu können, also füge ich meine Antwort hier ein.

Für Hostname - einfache Antwort, auf egrep Beispiel hier -- http: //www.linuxinsight.com/how_to_grep_for_ip_addresses_using_the_gnu_egrep_utility.html

egrep '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}'

Allerdings werden Werte wie 0 im ersten Oktett und Werte größer als 254 (IP-Adressen) oder 255 (Netzmaske) nicht berücksichtigt. Vielleicht würde eine zusätzliche if-Anweisung helfen.

Wie für legale DNS-Hostnamen, vorausgesetzt, dass Sie für Internet-Hostnamen nur (und nicht Intranet) überprüfen, schrieb ich die folgenden snipped, eine Mischung aus Shell/Php, aber es sollte als jeder regulären Ausdruck anwendbar sein.

Gehen Sie zunächst auf die ietf-Website, laden Sie eine Liste der legalen Level-1-Domänennamen herunter und analysieren Sie sie:

tld=$(curl -s http://data.iana.org/TLD/tlds-alpha-by-domain.txt |  sed 1d  | cut -f1 -d'-' | tr '\n' '|' | sed 's/\(.*\)./\1/')
echo "($tld)"

Das sollte Ihnen einen netten Code liefern, der die Rechtmäßigkeit des Top-Domain-Namens überprüft, wie .com .org oder .ca

Fügen Sie dann den ersten Teil des Ausdrucks gemäß den hier gefundenen Richtlinien ein - http: //www.domainit.com/support/faq.mhtml?category=Domain_FAQ&question=9 (eine beliebige alphanumerische Kombination und das Symbol '-', der Bindestrich sollte nicht am Anfang oder Ende eines Oktetts stehen.

(([a-z0-9]+|([a-z0-9]+[-]+[a-z0-9]+))[.])+

Dann fügen Sie alles zusammen (Beispiel PHP preg_match):

$pattern = '/^(([a-z0-9]+|([a-z0-9]+[-]+[a-z0-9]+))[.])+(AC|AD|AE|AERO|AF|AG|AI|AL|AM|AN|AO|AQ|AR|ARPA|AS|ASIA|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BIZ|BJ|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CAT|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|COM|COOP|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|INFO|INT|IO|IQ|IR|IS|IT|JE|JM|JO|JOBS|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MUSEUM|MV|MW|MX|MY|MZ|NA|NAME|NC|NE|NET|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|ORG|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PRO|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TEL|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TRAVEL|TT|TV|TW|TZ|UA|UG|UK|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XN|XN|XN|XN|XN|XN|XN|XN|XN|XN|XN|YE|YT|YU|ZA|ZM|ZW)[.]?$/i';

    if (preg_match, $pattern, $matching_string){
    ... do stuff
    }

Sie können auch eine if-Anweisung hinzufügen, um zu prüfen, ob die von Ihnen geprüfte Zeichenfolge kürzer als 256 Zeichen ist. http://www.ops.ietf.org/lists/namedroppers/namedroppers.2003/msg00964.html

4voto

abarnert Punkte 332066

Es ist erwähnenswert, dass es für die meisten Sprachen Bibliotheken gibt, die dies für Sie tun, oft in die Standardbibliothek integriert. Und diese Bibliotheken werden wahrscheinlich viel häufiger aktualisiert als Code, den Sie vor vier Jahren aus einer Stack Overflow-Antwort kopiert und dann vergessen haben. Und natürlich werden sie die Adresse in der Regel auch in eine brauchbare Form parsen, anstatt Ihnen nur eine Übereinstimmung mit einer Reihe von Gruppen zu liefern.

Zum Beispiel das Erkennen und Parsen von IPv4 in (POSIX) C:

#include <arpa/inet.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
  for (int i=1; i!=argc; ++i) {
    struct in_addr addr = {0};
    printf("%s: ", argv[i]);
    if (inet_pton(AF_INET, argv[i], &addr) != 1)
      printf("invalid\n");
    else
      printf("%u\n", addr.s_addr);
  }
  return 0;
}

Natürlich funktionieren solche Funktionen nicht, wenn Sie z. B. versuchen, alle gültigen Adressen in einer Chat-Nachricht zu finden - aber selbst da kann es einfacher sein, einen einfachen, aber übereifrigen Regex zu verwenden, um potenzielle Übereinstimmungen zu finden, und dann die Bibliothek zu verwenden, um sie zu parsen.

Zum Beispiel in Python:

>>> import ipaddress
>>> import re
>>> msg = "My address is 192.168.0.42; 192.168.0.420 is not an address"
>>> for maybeip in re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', msg):
...     try:
...         print(ipaddress.ip_address(maybeip))
...     except ValueError:
...         pass

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X