Expression régulière qui correspond aux adresses IPv6 valides


111

J'ai du mal à écrire une expression régulière qui correspond aux adresses IPv6 valides, y compris celles sous leur forme compressée (avec ::ou en tête des zéros omis de chaque paire d'octets).

Quelqu'un peut-il suggérer une expression régulière qui répondrait à l'exigence?

J'envisage d'étendre chaque paire d'octets et de faire correspondre le résultat avec une expression régulière plus simple.


1
Consultez intermapper.com/ipv6validator .. il est lié à ce script de test perl
Mottie

J'ai essayé toutes les réponses ci-dessous et elles ne fonctionnent pas pour tous mes cas de test et / ou elles incluent également IPv4 qui n'a pas été demandé. J'ai trouvé que c'était la solution la plus propre à ce jour: stackoverflow.com/a/21944928/3112803
gfrobenius

Réponses:


252

Je n'ai pas pu faire fonctionner la réponse de @Factor Mystic avec les expressions régulières POSIX, alors j'en ai écrit une qui fonctionne avec les expressions régulières POSIX et les expressions régulières PERL.

Il doit correspondre:

Expression régulière IPv6:

(([0-9a-fA-F]{1,4}:){7,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}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

Pour faciliter la lecture, voici l'expression régulière ci-dessus divisée aux principaux points OR en lignes séparées:

# IPv6 RegEx
(
([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|          # 1:2:3:4:5:6:7:8
([0-9a-fA-F]{1,4}:){1,7}:|                         # 1::                              1:2:3:4:5:6:7::
([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|         # 1::8             1:2:3:4:5:6::8  1:2:3:4:5:6::8
([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|  # 1::7:8           1:2:3:4:5::7:8  1:2:3:4:5::8
([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|  # 1::6:7:8         1:2:3:4::6:7:8  1:2:3:4::8
([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|  # 1::5:6:7:8       1:2:3::5:6:7:8  1:2:3::8
([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|  # 1::4:5:6:7:8     1:2::4:5:6:7:8  1:2::8
[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|       # 1::3:4:5:6:7:8   1::3:4:5:6:7:8  1::8  
:((:[0-9a-fA-F]{1,4}){1,7}|:)|                     # ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8 ::8       ::     
fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|     # fe80::7:8%eth0   fe80::7:8%1     (link-local IPv6 addresses with zone index)
::(ffff(:0{1,4}){0,1}:){0,1}
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|          # ::255.255.255.255   ::ffff:255.255.255.255  ::ffff:0:255.255.255.255  (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
([0-9a-fA-F]{1,4}:){1,4}:
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])           # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
)

# IPv4 RegEx
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])

Pour faciliter la compréhension de ce qui précède, le "pseudo" code suivant reproduit ce qui précède:

IPV4SEG  = (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])
IPV4ADDR = (IPV4SEG\.){3,3}IPV4SEG
IPV6SEG  = [0-9a-fA-F]{1,4}
IPV6ADDR = (
           (IPV6SEG:){7,7}IPV6SEG|                # 1:2:3:4:5:6:7:8
           (IPV6SEG:){1,7}:|                      # 1::                                 1:2:3:4:5:6:7::
           (IPV6SEG:){1,6}:IPV6SEG|               # 1::8               1:2:3:4:5:6::8   1:2:3:4:5:6::8
           (IPV6SEG:){1,5}(:IPV6SEG){1,2}|        # 1::7:8             1:2:3:4:5::7:8   1:2:3:4:5::8
           (IPV6SEG:){1,4}(:IPV6SEG){1,3}|        # 1::6:7:8           1:2:3:4::6:7:8   1:2:3:4::8
           (IPV6SEG:){1,3}(:IPV6SEG){1,4}|        # 1::5:6:7:8         1:2:3::5:6:7:8   1:2:3::8
           (IPV6SEG:){1,2}(:IPV6SEG){1,5}|        # 1::4:5:6:7:8       1:2::4:5:6:7:8   1:2::8
           IPV6SEG:((:IPV6SEG){1,6})|             # 1::3:4:5:6:7:8     1::3:4:5:6:7:8   1::8
           :((:IPV6SEG){1,7}|:)|                  # ::2:3:4:5:6:7:8    ::2:3:4:5:6:7:8  ::8       ::       
           fe80:(:IPV6SEG){0,4}%[0-9a-zA-Z]{1,}|  # fe80::7:8%eth0     fe80::7:8%1  (link-local IPv6 addresses with zone index)
           ::(ffff(:0{1,4}){0,1}:){0,1}IPV4ADDR|  # ::255.255.255.255  ::ffff:255.255.255.255  ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
           (IPV6SEG:){1,4}:IPV4ADDR               # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
           )

J'ai posté un script sur GitHub qui teste l'expression régulière: https://gist.github.com/syzdek/6086792


3
Votre regex IPv4 ne correspond pas aux adresses IP comme127.000.000.001
Kentzo

21
Les segments IPv4 ne doivent pas inclure de zéros non significatifs. Si un zéro non significatif est présent, le segment IPv4 doit être interprété en octal. Donc, l'IPV4SEG ci-dessus a raison de ne pas autoriser «000». Il autorise cependant «00», ce qu'il ne devrait pas.
par

3
Cela n'a pas fonctionné pour moi dans le navigateur comme je m'y attendais. Test de reg.test validé même ('3zzzzffe: 1900: 4545: 3: 200: f8ff: fe21: 67cf') qui n'est évidemment pas une adresse IPv6 valide. Nous
avons obtenu de

7
fantastique regex ipv6. trouvé un petit bug avec la section lien local. vous aviez fe80là où il devrait être quelque chose comme [fF][eE]80et un ffffqui devrait être quelque chose comme[fF]{4}
user2831628

4
+1 pour montrer que les expressions régulières peuvent être (de la même manière que n'importe quel code source) réellement lisibles si vous prenez soin de les formater.
Natix

52

Ce qui suit validera les adresses IPv4, IPv6 (complète et compressée) et IPv6v4 (complète et compressée):

'/^(?>(?>([a-f0-9]{1,4})(?>:(?1)){7}|(?!(?:.*[a-f0-9](?>:|$)){8,})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f0-9]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?4)){3}))$/iD'

8
Même si la validation des ip-s pourrait être effectuée comme le suggère Frank Krueger, cette solution est celle qui répond réellement à la question (même si je ne l'ai pas encore entièrement testée) ainsi que si vous avez de nombreuses IP que vous souhaitez tester syntaxiquement et peut-être correspondre dans une ligne de texte, vous ne pouvez pas utiliser la technique de validation IP.
Gyuri

Salut, j'ai testé ce RegExp et je n'ai pas travaillé pour moi. Il dit que D est un drapeau invalide et quand je le supprime, il dit "SyntaxError: invalid quantifier"
diosney

3
JavaScript implémente un sous-ensemble d'expressions régulières de style Perl, et non l'intégralité de PCRE. Mon regex ne fonctionnera pas sans certaines des fonctionnalités avancées de PCRE.
MichaelRushton

2
Cela me donne une exception en C #
sarat

1
Cas de test défaillant: FE80: 0000: 0000: 0000: 0202: B3FF: FE1E: 8329 Utilisation de la dernière version d'Elixir à cette date, qui utilise PCRE en dessous.
pmarreck

23

Il semble que vous utilisiez peut-être Python. Si tel est le cas, vous pouvez utiliser quelque chose comme ceci:

import socket

def check_ipv6(n):
    try:
        socket.inet_pton(socket.AF_INET6, n)
        return True
    except socket.error:
        return False

print check_ipv6('::1') # True
print check_ipv6('foo') # False
print check_ipv6(5)     # TypeError exception
print check_ipv6(None)  # TypeError exception

Je ne pense pas que vous deviez avoir IPv6 compilé dans Python pour obtenir inet_pton, qui peut également analyser les adresses IPv4 si vous passez en socket.AF_INETpremier paramètre. Remarque: cela peut ne pas fonctionner sur les systèmes non Unix.


4
Vous devez spécifier le type d'exception dans la exceptclause. Sinon, excepttout attrapera et peut masquer des erreurs sans rapport. Le type ici devrait être socket.error.
Ayman Hourieh

A) inet_pton ne lève pas d'autres exceptions, à moins que les documents ne soient faux, et B) même si c'était le cas, que renverriez-vous d'autre que False?
Joe Hildebrand

2
Re: autres erreurs ... si l'utilisateur passe une non-chaîne, TypeError est mangé. Clairement, une liste n'est pas un ipv6, mais je voudrais probablement l'avoir carpe que je passais dans le mauvais type.
Gregg Lind

1
+1 Cela m'a beaucoup aidé. Quelques points supplémentaires à ajouter: 1) socket.inet_pton peut être utilisé pour tester la validité des deux familles d'adresses IP (IP et IPv6). 2) Les documents ici ( docs.python.org/2/library/socket.html ) suggèrent que cela est disponible sur les plates-formes Unix. Il peut ne pas être disponible sur les plates-formes Win.
mkoistinen

en utilisant django et cela aide!
elad silver

23

À partir de « IPv6 regex »:

(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\Z)|
(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\Z)|
(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\Z)|
(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\Z)|
(\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\Z)|
(\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\Z)|
(\A(([0-9a-f]{1,4}:){1,7}|:):\Z)|
(\A:(:[0-9a-f]{1,4}){1,7}\Z)|
(\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|
(\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|
(\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)

45
Une expression régulière comme celle-ci devrait être une "odeur de code" que peut-être l'expression régulière n'est pas la meilleure solution ici. (Bien que je suppose que l'op l'a demandé ...)
Thanatos

10
@ user712092 - tous ceux qui ont vu une base de code avec des horreurs comme ça
danielpops

2
C'est une parodie totalement inutile pour les ER. Le programme qui l'a généré n'a pas compris ce qu'il faisait. Un humain ne ferait jamais cela de cette façon. Ne vous laissez pas berner par l'apparente complexité - les ER sont en effet de la «magie noire» pour beaucoup de gens, mais il n'y a aucune raison de les placer sur une autre planète!
Chuck Kollars

+1 mais OMG, il doit y avoir une meilleure façon de le faire: P Pour référence: pour Rails, cela pourrait aider: stackoverflow.com/questions/16965697/...
Tilo

1
C'est en effet une odeur de code; Cependant, après avoir jeté un œil, vous verrez que chaque expression régulière est assez concise. Le problème est qu'il existe différents modèles créés par la `` compression '' d'ipv6 - Colons début, milieu et fin, en plus si vous avez utilisé votre double deux-points, vous ne pouvez pas l'utiliser à nouveau, en plus du total deux points avant et après le double doivent s'additionner. Perl 6 pourrait peut- être résoudre ce problème, mais c'est bien au-delà de la syntaxe PCRE. (PS - Je ne compte pas l'ipv4 embarqué à la fin, qui est plus long que la section ipv6!)
Gerard ONeill

11

Je devrais fortement appuyer la réponse de Frank Krueger .

Alors que vous dites que vous avez besoin d'une expression régulière pour correspondre à une adresse IPv6, je suppose que ce dont vous avez vraiment besoin est de pouvoir vérifier si une chaîne donnée est une adresse IPv6 valide. Il y a ici une distinction subtile mais importante.

Il existe plusieurs façons de vérifier si une chaîne donnée est une adresse IPv6 valide et la correspondance d'expressions régulières n'est qu'une solution.

Utilisez une bibliothèque existante si vous le pouvez. La bibliothèque aura moins de bogues et son utilisation entraînera moins de code à maintenir.

L'expression régulière suggérée par Factor Mystic est longue et complexe. Cela fonctionne très probablement, mais vous devriez également réfléchir à la façon dont vous vous débrouilleriez en cas d'échec inattendu. Le point que j'essaie de faire ici est que si vous ne pouvez pas former vous-même une expression régulière requise, vous ne pourrez pas la déboguer facilement.

Si vous n'avez pas de bibliothèque appropriée, il peut être préférable d'écrire votre propre routine de validation IPv6 qui ne dépend pas d'expressions régulières. Si vous l'écrivez, vous le comprenez et si vous le comprenez, vous pouvez ajouter des commentaires pour l'expliquer afin que d'autres puissent également le comprendre et ensuite le maintenir.

Soyez prudent lorsque vous utilisez une expression régulière dont vous ne pouvez pas expliquer la fonctionnalité à quelqu'un d'autre.


1
L'utilisation de deux expressions régulières, une expression libérale et une expression d'exceptions pour intercepter les adresses non valides autorisées par la première, peut être plus facile qu'une seule expression ( return ex1.match(S) && ! ex2.match(S)).
Raedwald le

4
Vous supposez qu'il valide des adresses IP individuelles alors qu'il recherche presque certainement des adresses IP dans un grand bloc de texte.
Navin le

8

Je ne suis pas un expert Ipv6 mais je pense que vous pouvez obtenir un très bon résultat plus facilement avec celui-ci:

^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$

pour répondre "est un ipv6 valide" il me semble ok. Pour le décomposer en parties ... oubliez-le. J'ai omis celui non spécifié (: :) car il est inutile d'avoir une "adresse non spécifiée" dans ma base de données.

le début: ^([0-9A-Fa-f]{0,4}:){2,7}<- correspond à la partie compressible, nous pouvons traduire cela par: entre 2 et 7 deux points qui peuvent avoir un nombre heaxadécimal entre eux.

suivi de: [0-9A-Fa-f]{1,4}$<- un nombre hexadécimal (0 en tête omis) OU ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}<- une adresse Ipv4


1
+1 pour s'en tenir à la question des OP et présenter un regex relativement beau qui fonctionne un peu.
xebeche

1
Cela ne correspond pas à ":: 1"
lsalamon

Hein? Dans la syntaxe java regex, il correspond:start() = 0, end() = 3 group(0) = "::1" group(1) = ":" group(2) = "1" group(3) = "null" group(4) = "null" group(5) = "null"
Remi Morin

Quelque part ailleurs quelqu'un m'avertit d'un problème avec mon regex, la partie compressée "::" ne peut apparaître qu'une seule fois. Donc ":: 1 :: 2" correspondrait à mon regex mais ce n'est pas un IPV6 valide. Une deuxième regex peut valider ce cas. La recommandation complète était d'utiliser un analyseur avec état pour valider. Je suis d'accord que le code résultant sera plus facile à lire et à maintenir (et quelqu'un l'a probablement déjà codé dans un open source quelque part).
Remi Morin

8

Cela attrape également le bouclage (:: 1) et les adresses ipv6. changé {} en + et mettre: à l'intérieur du premier crochet carré.

([a-f0-9:]+:+)+[a-f0-9]+

testé avec ifconfig -a output http://regexr.com/

L'option o terminal Unix ou Mac OSx renvoie uniquement la sortie correspondante (ipv6) comprenant :: 1

ifconfig -a | egrep -o '([a-f0-9:]+:+)+[a-f0-9]+'

Obtenez toutes les adresses IP (IPv4 OU IPv6) et imprimez la correspondance sur le terme unix OSx

ifconfig -a | egrep -o '([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) | (([a-f0-9:]+:+)+[a-f0-9]+)'

J'aime la simplicité. Cela a finalement fonctionné pour moi:ip a | grep -Po '[\w:]+:+[\w:]+'
Noam Manos

Humour apprécié!
Soumya Kanti

Lorsque j'exécute ipconfig / all, mon adresse IP se termine par% 10, cette expression ne correspond pas à cette partie?
Peter

7

Cette expression régulière correspondra aux adresses IPv6 et IPv4 valides conformément à l'implémentation GNU C ++ de regex avec le mode REGULAR EXTENDED utilisé:

"^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?\s*$"

5

Il faut se méfier! En Java, l'utilisation d'InetAddress et des classes associées (Inet4Address, Inet6Address, URL) peut impliquer du trafic réseau! Par exemple, la résolution DNS (URL.equals, InetAddress from string!). Cet appel peut prendre du temps et se bloque!

Pour IPv6, j'ai quelque chose comme ça. Bien sûr, cela ne gère pas les détails très subtils d'IPv6, comme le fait que les indices de zone ne sont autorisés que sur certaines classes d'adresses IPv6. Et cette expression régulière n'est pas écrite pour la capture de groupe, c'est seulement une sorte d'expression régulière "correspond".

S - Segment IPv6 = [0-9a-f]{1,4}

I - IPv4 = (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})

Schéma (la première partie correspond aux adresses IPv6 avec le suffixe IPv4, la deuxième partie correspond aux adresses IPv6, le dernier chemin correspond à l'index de la zone):

(
(
::(S:){0,5}|
S::(S:){0,4}|
(S:){2}:(S:){0,3}|
(S:){3}:(S:){0,2}|
(S:){4}:(S:)?|
(S:){5}:|
(S:){6}
)
I

|

:(:|(:S){1,7})|
S:(:|(:S){1,6})|
(S:){2}(:|(:S){1,5})|
(S:){3}(:|(:S){1,4})|
(S:){4}(:|(:S){1,3})|
(S:){5}(:|(:S){1,2})|
(S:){6}(:|(:S))|
(S:){7}:|
(S:){7}S
)

(?:%[0-9a-z]+)?

Et ici, l'expression rationnelle might (insensible à la casse, entoure ce qui a jamais été nécessaire, comme le début / la fin de la ligne, etc.):

(?:
(?:
::(?:[0-9a-f]{1,4}:){0,5}|
[0-9a-f]{1,4}::(?:[0-9a-f]{1,4}:){0,4}|
(?:[0-9a-f]{1,4}:){2}:(?:[0-9a-f]{1,4}:){0,3}|
(?:[0-9a-f]{1,4}:){3}:(?:[0-9a-f]{1,4}:){0,2}|
(?:[0-9a-f]{1,4}:){4}:(?:[0-9a-f]{1,4}:)?|
(?:[0-9a-f]{1,4}:){5}:|
(?:[0-9a-f]{1,4}:){6}
)
(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})|

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

(?:%[0-9a-z]+)?

4

L'expression régulière suivante est pour IPv6 uniquement. Le groupe 1 correspond à l'IP.

(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})

+1 Il n'est pas toujours nécessaire d'avoir une regex super complexe parfaite qu'un humain ne peut pas comprendre. J'utiliserai celui-ci parce que je comprends ce qu'il fait et dans mon cas, je peux être sûr que si j'ai quelque chose qui ressemble à un ipv6 valide, il s'agit donc d'un ipv6 valide.
David L.

3
cela ne correspond pas à dire: fe80 :: 1 ou 2342: 32fd :: 2d32
James

3

Une simple expression régulière qui correspondra, mais je ne recommanderais aucune validation de quelque sorte que ce soit:

([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}

Notez que cela correspond à la compression n'importe où dans l'adresse, bien que cela ne corresponde pas à l'adresse de bouclage :: 1. Je trouve que c'est un compromis raisonnable afin de garder la regex simple.

J'utilise avec succès cela dans les règles de sélection intelligente iTerm2 pour quad-cliquer sur les adresses IPv6.


3
Vous vouliez A-Fdire non A-Z! Notez également que vous excluez la notation quadruple pointée.
xebeche


2

Dans Scala, utilisez les validateurs Apache Commons bien connus.

http://mvnrepository.com/artifact/commons-validator/commons-validator/1.4.1

libraryDependencies += "commons-validator" % "commons-validator" % "1.4.1"


import org.apache.commons.validator.routines._

/**
 * Validates if the passed ip is a valid IPv4 or IPv6 address.
 *
 * @param ip The IP address to validate.
 * @return True if the passed IP address is valid, false otherwise.
 */  
 def ip(ip: String) = InetAddressValidator.getInstance().isValid(ip)

Suite aux tests de la méthode ip(ip: String):

"The `ip` validator" should {
  "return false if the IPv4 is invalid" in {
    ip("123") must beFalse
    ip("255.255.255.256") must beFalse
    ip("127.1") must beFalse
    ip("30.168.1.255.1") must beFalse
    ip("-1.2.3.4") must beFalse
  }

  "return true if the IPv4 is valid" in {
    ip("255.255.255.255") must beTrue
    ip("127.0.0.1") must beTrue
    ip("0.0.0.0") must beTrue
  }

  //IPv6
  //@see: http://www.ronnutter.com/ipv6-cheatsheet-on-identifying-valid-ipv6-addresses/
  "return false if the IPv6 is invalid" in {
    ip("1200::AB00:1234::2552:7777:1313") must beFalse
  }

  "return true if the IPv6 is valid" in {
    ip("1200:0000:AB00:1234:0000:2552:7777:1313") must beTrue
    ip("21DA:D3:0:2F3B:2AA:FF:FE28:9C5A") must beTrue
  }
}

Intéressant, il prétend vérifier qu'il s'agit d'une adresse valide, " Valide si l'IP transmise est une adresse IPv4 ou IPv6 valide. ", Mais il vérifie vraiment seulement qu'elle est formatée comme une adresse valide. Par exemple, 1200:0000:AB00:1234:0000:2552:7777:1313est un format valide pour une adresse IPv6, mais ce n'est pas une adresse IPv6 valide comme le renvoie la méthode de test. Je parie qu'il pense que 241.54.113.65c'est une adresse IPv4 valide.
Ron Maupin

2

En regardant les modèles inclus dans les autres réponses, il existe un certain nombre de bons modèles qui peuvent être améliorés en référençant des groupes et en utilisant des anticipations. Voici un exemple de modèle d'auto-référencement que j'utiliserais en PHP si je devais:

^(?<hgroup>(?<hex>[[:xdigit:]]{0,4}) # grab a sequence of up to 4 hex digits
                                     # and name this pattern for usage later
     (?<!:::):{1,2})                 # match 1 or 2 ':' characters
                                     # as long as we can't match 3
 (?&hgroup){1,6} # match our hex group 1 to 6 more times
 (?:(?:
    # match an ipv4 address or
    (?<dgroup>2[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(?&dgroup)
    # match our hex group one last time
    |(?&hex))$

Remarque: PHP a un filtre intégré pour cela, ce qui serait une meilleure solution que ce modèle.

Analyse Regex101


2

J'ai généré ce qui suit en utilisant python et fonctionne avec le module re. Les affirmations d'anticipation garantissent que le nombre correct de points ou de deux points apparaît dans l'adresse. Il ne prend pas en charge IPv4 en notation IPv6.

pattern = '^(?=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)(?:(?:25[0-5]|[12][0-4][0-9]|1[5-9][0-9]|[1-9]?[0-9])\.?){4}$|(?=^(?:[0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}$)(?![^:]*::.+::[^:]*$)(?:(?=.*::.*)|(?=\w+:\w+:\w+:\w+:\w+:\w+:\w+:\w+))(?:(?:^|:)(?:[0-9a-f]{4}|[1-9a-f][0-9a-f]{0,3})){0,8}(?:::(?:[0-9a-f]{1,4}(?:$|:)){0,6})?$'
result = re.match(pattern, ip)
if result: result.group(0)

2

Les expressions régulières pour ipv6 peuvent devenir très délicates lorsque vous considérez les adresses avec ipv4 intégré et les adresses compressées, comme vous pouvez le voir à partir de certaines de ces réponses.

La bibliothèque Java IPAddress open source validera toutes les représentations standard d'IPv6 et IPv4 et prend également en charge la longueur du préfixe (et la validation de celle-ci). Avertissement: je suis le chef de projet de cette bibliothèque.

Exemple de code:

        try {
            IPAddressString str = new IPAddressString("::1");
            IPAddress addr = str.toAddress();
            if(addr.isIPv6() || addr.isIPv6Convertible()) {
                IPv6Address ipv6Addr = addr.toIPv6();
            }
            //use address
        } catch(AddressStringException e) {
            //e.getMessage has validation error
        }

1

En Java, vous pouvez utiliser la classe de bibliothèque sun.net.util.IPAddressUtil:

IPAddressUtil.isIPv6LiteralAddress(iPaddress);

3
sun.net. * est une API privée.
David Kocher

1

Il est difficile de trouver une expression régulière qui fonctionne pour tous les cas IPv6. Ils sont généralement difficiles à maintenir, difficilement lisibles et peuvent entraîner des problèmes de performances. Par conséquent, je souhaite partager une solution alternative que j'ai développée: Expression régulière (RegEx) pour IPv6 séparée de IPv4

Maintenant, vous pouvez demander que "Cette méthode ne trouve qu'IPv6, comment puis-je trouver IPv6 dans un texte ou un fichier?" Voici également des méthodes pour ce problème.

Remarque : Si vous ne souhaitez pas utiliser la classe IPAddress dans .NET, vous pouvez également la remplacer par ma méthode . Il couvre également l'IPv4 mappé et les cas spéciaux, tandis que IPAddress ne couvre pas.

class IPv6
{
    public List<string> FindIPv6InFile(string filePath)
    {
        Char ch;
        StringBuilder sbIPv6 = new StringBuilder();
        List<string> listIPv6 = new List<string>();
        StreamReader reader = new StreamReader(filePath);
        do
        {
            bool hasColon = false;
            int length = 0;

            do
            {
                ch = (char)reader.Read();

                if (IsEscapeChar(ch))
                    break;

                //Check the first 5 chars, if it has colon, then continue appending to stringbuilder
                if (!hasColon && length < 5)
                {
                    if (ch == ':')
                    {
                        hasColon = true;
                    }
                    sbIPv6.Append(ch.ToString());
                }
                else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder
                {
                    sbIPv6.Append(ch.ToString());
                }

                length++;

            } while (!reader.EndOfStream);

            if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))
            {
                listIPv6.Add(sbIPv6.ToString());
            }

            sbIPv6.Clear();

        } while (!reader.EndOfStream);
        reader.Close();
        reader.Dispose();

        return listIPv6;
    }

    public List<string> FindIPv6InText(string text)
    {
        StringBuilder sbIPv6 = new StringBuilder();
        List<string> listIPv6 = new List<string>();

        for (int i = 0; i < text.Length; i++)
        {
            bool hasColon = false;
            int length = 0;

            do
            {
                if (IsEscapeChar(text[length + i]))
                    break;

                //Check the first 5 chars, if it has colon, then continue appending to stringbuilder
                if (!hasColon && length < 5)
                {
                    if (text[length + i] == ':')
                    {
                        hasColon = true;
                    }
                    sbIPv6.Append(text[length + i].ToString());
                }
                else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder
                {
                    sbIPv6.Append(text[length + i].ToString());
                }

                length++;

            } while (i + length != text.Length);

            if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))
            {
                listIPv6.Add(sbIPv6.ToString());
            }

            i += length;
            sbIPv6.Clear();
        }

        return listIPv6;
    }

    bool IsEscapeChar(char ch)
    {
        if (ch != ' ' && ch != '\r' && ch != '\n' && ch!='\t')
        {
            return false;
        }

        return true;
    }

    bool IsIPv6(string maybeIPv6)
    {
        IPAddress ip;
        if (IPAddress.TryParse(maybeIPv6, out ip))
        {
            return ip.AddressFamily == AddressFamily.InterNetworkV6;
        }
        else
        {
            return false;
        }
    }

}

1

InetAddressUtilsa tous les modèles définis. J'ai fini par utiliser leur modèle directement, et je le colle ici pour référence:

private static final String IPV4_BASIC_PATTERN_STRING =
        "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by .
         "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255

private static final Pattern IPV4_PATTERN =
    Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$");

private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros
        Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$");

private static final Pattern IPV6_STD_PATTERN =
    Pattern.compile(
            "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$");

private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
    Pattern.compile(
            "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields
             "::" +
             "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields 

1

Vous utilisez Ruby? Essaye ça:

/^(((?=.*(::))(?!.*\3.+\3))\3?|[\dA-F]{1,4}:)([\dA-F]{1,4}(\3|:\b)|\2){5}(([\dA-F]{1,4}(\3|:\b|$)|\2){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})\z/i

1

En fonction de vos besoins, une approximation comme:

[0-9a-f:]+

peut suffire (comme avec un simple grepping de fichier journal, par exemple).


0

Pour les utilisateurs de PHP 5.2+, cela filter_varfonctionne très bien.

Je sais que cela ne répond pas à la question originale (en particulier une solution regex), mais je publie ceci dans l'espoir que cela puisse aider quelqu'un d'autre à l'avenir.

$is_ip4address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE);
$is_ip6address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE);

0

Cela fonctionnera pour IPv4 et IPv6:

^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$

2
Il correspond aux adresses non valides avec 2 instances de ::. eg2404:6800::4003:c02::8a
nhahtdh

correspond à IPv4 666.666.666.666 invalide
Ryan Williams

0

Voici ce que j'ai trouvé, en utilisant un peu d'anticipation et des groupes nommés. Il s'agit bien sûr d'IPv6, mais cela ne devrait pas interférer avec des modèles supplémentaires si vous souhaitez ajouter IPv4:

(?=([0-9a-f]+(:[0-9a-f])*)?(?P<wild>::)(?!([0-9a-f]+:)*:))(::)?([0-9a-f]{1,4}:{1,2}){0,6}(?(wild)[0-9a-f]{0,4}|[0-9a-f]{1,4}:[0-9a-f]{1,4})


0

Correspondant simplement à ceux locaux d'une origine avec des crochets inclus. Je sais que ce n'est pas aussi complet, mais en javascript, les autres avaient du mal à retracer les problèmes principalement de ne pas fonctionner, donc cela semble me donner ce dont j'avais besoin pour le moment. des majuscules supplémentaires AF ne sont pas nécessaires non plus.

^\[([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})\]

La version de Jinnko est simplifiée et meilleure je vois.


0

Comme indiqué ci-dessus, une autre façon d'obtenir une représentation textuelle IPv6 validant l' analyseur est d'utiliser la programmation. En voici un qui est entièrement conforme aux RFC-4291 et RFC-5952. J'ai écrit ce code en ANSI C (fonctionne avec GCC, passé des tests sur Linux - fonctionne avec clang, passé des tests sur FreeBSD). Ainsi, il ne repose que sur la bibliothèque standard ANSI C, donc il peut être compilé partout (je l'ai utilisé pour l'analyse IPv6 à l'intérieur d'un module de noyau avec FreeBSD).

// IPv6 textual representation validating parser fully compliant with RFC-4291 and RFC-5952
// BSD-licensed / Copyright 2015-2017 Alexandre Fenyo

#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

typedef enum { false, true } bool;

static const char hexdigits[] = "0123456789abcdef";
static int digit2int(const char digit) {
  return strchr(hexdigits, digit) - hexdigits;
}

// This IPv6 address parser handles any valid textual representation according to RFC-4291 and RFC-5952.
// Other representations will return -1.
//
// note that str input parameter has been modified when the function call returns
//
// parse_ipv6(char *str, struct in6_addr *retaddr)
// parse textual representation of IPv6 addresses
// str:     input arg
// retaddr: output arg
int parse_ipv6(char *str, struct in6_addr *retaddr) {
  bool compressed_field_found = false;
  unsigned char *_retaddr = (unsigned char *) retaddr;
  char *_str = str;
  char *delim;

  bzero((void *) retaddr, sizeof(struct in6_addr));
  if (!strlen(str) || strchr(str, ':') == NULL || (str[0] == ':' && str[1] != ':') ||
      (strlen(str) >= 2 && str[strlen(str) - 1] == ':' && str[strlen(str) - 2] != ':')) return -1;

  // convert transitional to standard textual representation
  if (strchr(str, '.')) {
    int ipv4bytes[4];
    char *curp = strrchr(str, ':');
    if (curp == NULL) return -1;
    char *_curp = ++curp;
    int i;
    for (i = 0; i < 4; i++) {
      char *nextsep = strchr(_curp, '.');
      if (_curp[0] == '0' || (i < 3 && nextsep == NULL) || (i == 3 && nextsep != NULL)) return -1;
      if (nextsep != NULL) *nextsep = 0;
      int j;
      for (j = 0; j < strlen(_curp); j++) if (_curp[j] < '0' || _curp[j] > '9') return -1;
      if (strlen(_curp) > 3) return -1;
      const long val = strtol(_curp, NULL, 10);
      if (val < 0 || val > 255) return -1;
      ipv4bytes[i] = val;
      _curp = nextsep + 1;
    }
    sprintf(curp, "%x%02x:%x%02x", ipv4bytes[0], ipv4bytes[1], ipv4bytes[2], ipv4bytes[3]);
  }

  // parse standard textual representation
  do {
    if ((delim = strchr(_str, ':')) == _str || (delim == NULL && !strlen(_str))) {
      if (delim == str) _str++;
      else if (delim == NULL) return 0;
      else {
        if (compressed_field_found == true) return -1;
        if (delim == str + strlen(str) - 1 && _retaddr != (unsigned char *) (retaddr + 1)) return 0;
        compressed_field_found = true;
        _str++;
        int cnt = 0;
        char *__str;
        for (__str = _str; *__str; ) if (*(__str++) == ':') cnt++;
        unsigned char *__retaddr = - 2 * ++cnt + (unsigned char *) (retaddr + 1);
        if (__retaddr <= _retaddr) return -1;
        _retaddr = __retaddr;
      }
    } else {
      char hexnum[4] = "0000";
      if (delim == NULL) delim = str + strlen(str);
      if (delim - _str > 4) return -1;
      int i;
      for (i = 0; i < delim - _str; i++)
        if (!isxdigit(_str[i])) return -1;
        else hexnum[4 - (delim - _str) + i] = tolower(_str[i]);
      _str = delim + 1;
      *(_retaddr++) = (digit2int(hexnum[0]) << 4) + digit2int(hexnum[1]);
      *(_retaddr++) = (digit2int(hexnum[2]) << 4) + digit2int(hexnum[3]);
    }
  } while (_str < str + strlen(str));
  return 0;
}

-1

Essayez ce petit one-liner. Il doit uniquement correspondre aux adresses IPv6 non compressées / compressées valides (pas d'hybrides IPv4)

/(?!.*::.*::)(?!.*:::.*)(?!:[a-f0-9])((([a-f0-9]{1,4})?[:](?!:)){7}|(?=(.*:[:a-f0-9]{1,4}::|^([:a-f0-9]{1,4})?::))(([a-f0-9]{1,4})?[:]{1,2}){1,6})[a-f0-9]{1,4}/

En fait, les adresses IPv6 valides incluent les adresses non compressées, compressées, hybrides non compressées et hybrides compressées. Il en faut vraiment beaucoup plus que ce que vous avez pour correspondre à une représentation textuelle valide d'une adresse IPv6.
Ron Maupin

-2

Le regex permet l'utilisation de zéros non significatifs dans les parties IPv4.

Certaines distributions Unix et Mac convertissent ces segments en octals.

Je suggère d'utiliser 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\dcomme segment IPv4.


-2

Si vous ne voulez que des IP-s normaux (pas de barres obliques), ici:

^(?:[0-9a-f]{1,4}(?:::)?){0,7}::[0-9a-f]+$

Je l'utilise pour mon surligneur de syntaxe dans l'application de l'éditeur de fichiers hôtes. Fonctionne comme un charme.


Pas question que cela fonctionne correctement, cela ne peut pas correspondre à une seule adresse ipv6 avec un seul deux-points, toutes vos correspondances sont sur des doubles-virgules, et vous avez explicitement besoin d'un double-deux-points pour votre dernier groupe, la synthèse peut se produire n'importe où. .
KillianDS

(?: [0-9a-f] {1,4} (? :::?)?) {0,7} ::? [0-9a-f] {1,4}
Harry

Toujours faux, mais même dans ce cas, vous finirez par répéter la réponse de JinnKo, ce qui est assez bon pour des raisons simples, mais a toujours des défauts (n'attrape pas le double résumé et n'autorise pas les quads pointés, ni localhost, ni :: terminaison,. ..)
KillianDS
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.