web-dev-qa-db-fra.com

Expression régulière pour faire correspondre le nom d’hôte DNS ou l’adresse IP?

Quelqu'un at-il une expression régulière à portée de main qui correspond à n’importe quel nom d’hôte ou adresse IP DNS légal?

Il est facile d'en écrire un qui fonctionne 95% du temps, mais j'espère obtenir quelque chose qui a été bien testé pour correspondre exactement aux dernières spécifications RFC pour les noms d'hôte DNS.

353
DonGar

Vous pouvez utiliser les expressions régulières suivantes séparément ou en les combinant dans une expression conjointe OR.

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 correspond aux adresses IP valides et ValidHostnameRegex noms d'hôtes valides. En fonction de la langue que vous utilisez, il pourrait être nécessaire d'échapper à \.


ValidHostnameRegex est valide conformément à RFC 112 . À l'origine, RFC 952 spécifiait que les segments de nom d'hôte ne pouvaient pas commencer par un chiffre.

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

La spécification d'origine des noms d'hôte dans RFC 952 , stipulait que les étiquettes ne pouvaient pas commencer par un chiffre ni par un trait d'union et ne devaient pas se terminer par un trait d'union. Cependant, une spécification ultérieure ( RFC 112 ) permettait aux étiquettes de nom d'hôte de commencer par des chiffres.

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])$";
512
Jorge Ferreira

Le nom d'hôte regex de smink n'observe pas la limitation de la longueur des étiquettes individuelles dans un nom d'hôte. Chaque étiquette dans un nom d'hôte valide ne doit pas dépasser 63 octets.

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])) * $ "

Notez que la barre oblique inverse à la fin de la première ligne (ci-dessus) correspond à la syntaxe Unix Shell permettant de scinder la ligne longue. Cela ne fait pas partie de l'expression régulière elle-même.

Voici juste l'expression régulière seule sur une seule ligne:

^ ([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])) * $

Vous devez également vérifier séparément que la longueur totale du nom d’hôte ne doit pas dépasser 255 caractères. Pour plus d'informations, veuillez consulter les documents RFC-952 et RFC-1123.

61
Sakari A. Maaranen

Pour faire correspondre une adresse IP valide , utilisez la regex suivante:

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

au lieu de:

([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}

Explication

De nombreux moteurs de regex correspondent à la première possibilité de la séquence OR. Par exemple, essayez l'expression régulière suivante:

10.48.0.200

Tester

Testez la différence entre bien vs mauvais

31
Alban

Je ne semble pas être en mesure de modifier le message en haut, je vais donc ajouter ma réponse ici.

Pour le nom d’hôte - réponse simple, exemple egrep ici - http: //www.linuxinsight.com/how_to_grep_for_ip_addresses_using_the_gnu_egrep_utility.html

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

Bien que le cas ne tienne pas compte de valeurs telles que 0 dans le premier octet et de valeurs supérieures à 254 (adresse IP) ou 255 (masque de réseau). Peut-être une déclaration supplémentaire si aiderait.

En ce qui concerne le nom d’hôte légal du DNS, à condition que vous vérifiiez uniquement les noms d’hôte Internet (et non l’intranet), j’ai écrit ce qui suit: un mélange de Shell/php, mais il devrait s’appliquer à toute expression régulière.

d'abord, allez sur le site Web d'ietf, téléchargez et analysez une liste de noms de domaines juridiques de niveau 1:

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)"

Cela devrait vous donner un joli code de code qui vérifie la légalité du nom de domaine le plus performant, tel que .com .org ou .ca

Ajoutez ensuite la première partie de l’expression conformément aux instructions indiquées ici - http: //www.domainit.com/support/faq.mhtml?category=Domain_FAQ&question=9 (toute combinaison alphanumérique et le symbole '-', le tiret ne doit pas figurer). le début ou la fin d'un octet.

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

Ensuite, mettez le tout ensemble (exemple 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
    }

Vous pouvez également ajouter une instruction if pour vérifier que la chaîne vérifiée est inférieure à 256 caractères - http://www.ops.ietf.org/lists/namedroppers/namedroppers.2003/msg00964.html

4
Alex Volkov
def isValidHostname(hostname):

    if len(hostname) > 255:
        return False
    if hostname[-1:] == ".":
        hostname = hostname[:-1]   # strip exactly one dot from the right,
                                   #  if present
    allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
    return all(allowed.match(x) for x in hostname.split("."))
2
PythonDev

Il est à noter qu'il existe des bibliothèques pour la plupart des langues qui le font pour vous, souvent intégrées à la bibliothèque standard. Et ces bibliothèques seront probablement mises à jour beaucoup plus souvent que le code que vous avez copié à partir d'une réponse Stack Overflow il y a quatre ans et que vous avez oublié. Et bien sûr, ils vont généralement également analyser l'adresse sous une forme utilisable, plutôt que de vous donner une correspondance avec un groupe de groupes.

Par exemple, détecter et analyser IPv4 dans (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;
}

Évidemment, de telles fonctions ne fonctionneront pas si vous essayez, par exemple, de trouver toutes les adresses valides dans un message de chat. Mais même dans ce cas, il peut être plus facile d’utiliser une expression rationnelle simple mais trop zélée pour rechercher des correspondances potentielles, puis d’utiliser la fonction. bibliothèque pour les analyser.

Par exemple, en 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
2
abarnert

Je pense que c'est la meilleure regex de validation IP. s'il vous plaît vérifier une fois !!!

^(([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))\.){3}([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))$
1
Prakash Thapa

Cela fonctionne pour les adresses IP valides:

regex = '^([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])[.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])[.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])[.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])$'
1
aliasav
/^(?:[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])?$/

localhost же есть

1
user2240578
"^((\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\.){3}(\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])$"
1
zangw

La nouvelle infrastructure réseau comporte des initialiseurs disponibles pour struct IPv4Address et struct IPv6Address, qui gèrent très facilement la partie adresse IP. Faire cela en IPv6 avec une regex est difficile avec toutes les règles de raccourcissement.

Malheureusement, je n'ai pas de réponse élégante pour le nom d'hôte.

Notez que la structure réseau est récente, elle peut donc vous obliger à compiler pour les versions récentes du système d'exploitation.

import Network
let tests = ["192.168.4.4","fkjhwojfw","192.168.4.4.4","2620:3","2620::33"]

for test in tests {
    if let _ = IPv4Address(test) {
        debugPrint("\(test) is valid ipv4 address")
    } else if let _ = IPv6Address(test) {
        debugPrint("\(test) is valid ipv6 address")
    } else {
        debugPrint("\(test) is not a valid IP address")
    }
}

output:
"192.168.4.4 is valid ipv4 address"
"fkjhwojfw is not a valid IP address"
"192.168.4.4.4 is not a valid IP address"
"2620:3 is not a valid IP address"
"2620::33 is valid ipv6 address"
0
Darrell Root

J'ai trouvé que cela fonctionne assez bien pour les adresses IP. Il valide comme la réponse du haut mais s'assure également que l'ip est isolé afin qu'aucun texte ou plus de nombres/décimales ne se trouvent avant ou avant l'ip.

(? <!\S) (?: (?:\D | [1-9]\d | 1\d\d | 2 [0-4]\d | 25 [0-5])\b |.\b) {7} (?!\S)

0
Andrew
>>> my_hostname = "testhostn.ame"
>>> print bool(re.match("^(([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])$", my_hostname))
True
>>> my_hostname = "testhostn....ame"
>>> print bool(re.match("^(([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])$", my_hostname))
False
>>> my_hostname = "testhostn.A.ame"
>>> print bool(re.match("^(([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])$", my_hostname))
True

En ce qui concerne les adresses IP, il semble qu'il y ait un débat sur l'opportunité d'inclure les zéros non significatifs. C'était une fois la pratique courante et est généralement acceptée, donc je dirais qu'ils devraient être marqués comme valides indépendamment de la préférence actuelle. Il y a également une certaine ambiguïté quant à savoir si le texte avant et après la chaîne doit être validé et, encore une fois, je le pense. 1.2.3.4 est une adresse IP valide, mais 1.2.3.4.5 ne l’est pas et ni la partie 1.2.3.4, ni la partie 2.3.4.5 ne doivent donner lieu à une correspondance. Certaines des préoccupations peuvent être traitées avec cette expression:

grep -E '(^|[^[:alnum:]+)(([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])([^[:alnum:]]|$)' 

La partie malheureuse ici est le fait que la portion de regex qui valide un octet est répétée comme c'est le cas dans de nombreuses solutions proposées. Bien que cela soit mieux que pour les instances du motif, la répétition peut être entièrement éliminée si les sous-routines sont prises en charge dans la regex utilisée. L'exemple suivant active ces fonctions avec le commutateur -P de grep et tire également parti des fonctionnalités de visualisation anticipée et différée. (Le nom de la fonction que j'ai sélectionné est "o" pour octet. J'aurais pu utiliser "octet" comme nom mais je voulais être concis.)

grep -P '(?<![\d\w\.])(?<o>([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(\.\g<o>){3}(?![\d\w\.])'

Le traitement du point peut en réalité créer un faux négatif si les adresses IP sont dans un fichier avec du texte sous forme de phrases, car la période pourrait suivre sans que cela fasse partie de la notation en pointillé. Une variante de ce qui précède permettrait de résoudre ce problème:

grep -P '(?<![\d\w\.])(?<x>([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(\.\g<x>){3}(?!([\d\w]|\.\d))'
0
Thom Anderson

Voici une expression régulière que j'ai utilisée dans Ant pour obtenir une adresse IP hôte ou un nom d'hôte proxy sur ANT_OPTS. Cela a été utilisé pour obtenir l'adresse IP du proxy afin que je puisse exécuter un test Ant "inaccessible" avant de configurer un proxy pour une machine virtuelle Java fourchue.

^.*-Dhttp\.proxyHost=(\w{1,}\.\w{1,}\.\w{1,}\.*\w{0,})\s.*$
0
Bill Stephens

essaye ça:

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

cela fonctionne dans mon cas.

0
seraphim
AddressRegex = "^(ftp|http|https):\/\/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5})$";

HostnameRegex =  /^(ftp|http|https):\/\/([a-z0-9]+\.)?[a-z0-9][a-z0-9-]*((\.[a-z]{2,6})|(\.[a-z]{2,6})(\.[a-z]{2,6}))$/i

ces re sont utilisés uniquement pour la validation de ce type

ne fonctionne que si http://www.kk.comhttp://www.kk.co .in

ne fonctionne pas pour

http://www.kk.com/http: //www.kk.co.in.kk

http://www.kk.com/dfashttp://www.kk.co.in/

0
ayu for u