regex - Expresión regular que coincide con direcciones IPv6 válidas
networking (30)
¡Tener cuidado! En Java, el uso de InetAddress y las clases relacionadas (Inet4Address, Inet6Address, URL) pueden implicar tráfico de red. Por ejemplo, resolución DNS (URL.equals, InetAddress from string!). ¡Esta llamada puede llevar mucho tiempo y está bloqueando!
Para IPv6 tengo algo como esto. Por supuesto, esto no maneja los detalles muy sutiles de IPv6, como que los índices de zona solo están permitidos en algunas clases de direcciones IPv6. Y esta expresión regular no está escrita para la captura de grupos, solo es un tipo de expresiones regulares "equivalentes".
S
- segmento 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})
Esquema (la primera parte coincide con las direcciones IPv6 con el sufijo IPv4, la segunda parte con las direcciones IPv6, el último con el índice de la zona):
(
(
::(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]+)?
Y aquí el podría regex (mayúsculas y minúsculas, envolvente con lo que alguna vez necesitó como principio / fin de línea, 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]+)?
Tengo problemas para escribir una expresión regular que coincida con direcciones IPv6 válidas, incluidas aquellas en su forma comprimida (con ::
o ceros a la izquierda omitidos de cada par de bytes).
¿Alguien puede sugerir una expresión regular que cumpla con el requisito?
Estoy considerando expandir cada par de bytes y hacer coincidir el resultado con una expresión regular más simple.
¿Usando Ruby? Prueba esto:
/^(((?=.*(::))(?!.*/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
Al observar los patrones incluidos en las otras respuestas, hay una serie de buenos patrones que se pueden mejorar haciendo referencia a grupos y utilizando lookaheads. Aquí hay un ejemplo de un patrón que se autorreferencia que utilizaría en PHP si tuviera que:
^(?<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))$
Nota: PHP tiene un filtro incorporado para esto que sería una mejor solución que este patrón.
Como se indicó anteriormente, otra forma de obtener una representación textual IPv6 validando el analizador es usar la programación. Aquí hay uno que cumple totalmente con RFC-4291 y RFC-5952. Escribí este código en ANSI C (funciona con GCC, pasé las pruebas en Linux - funciona con clang, pasé las pruebas en FreeBSD). Por lo tanto, solo se basa en la biblioteca estándar ANSI C, por lo que se puede compilar en todas partes (lo he usado para el análisis de IPv6 dentro de un módulo kernel con 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;
}
Dependiendo de sus necesidades, una aproximación como:
[0-9a-f:]+
puede ser suficiente (como con el simple almacenamiento de archivos de registro, por ejemplo).
Desde " 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)
En Scala usa los conocidos validadores de Apache Commons.
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)
Siguiendo las pruebas del método 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
}
}
En Java, puede usar la clase de biblioteca sun.net.util.IPAddressUtil
:
IPAddressUtil.isIPv6LiteralAddress(iPaddress);
Es difícil encontrar una expresión regular que funcione para todos los casos de IPv6. Por lo general, son difíciles de mantener, no son fáciles de leer y pueden causar problemas de rendimiento. Por lo tanto, quiero compartir una solución alternativa que he desarrollado: Expresión regular (RegEx) para IPv6 Separado de IPv4
Ahora puede preguntar: "Este método solo encuentra IPv6, ¿cómo puedo encontrar IPv6 en un texto o archivo?" Aquí hay métodos para este problema también.
Nota : Si no desea usar la clase IPAddress en .NET, también puede reemplazarla con mi método . También cubre IPv4 asignado y casos especiales también, mientras que IPAddress no cubre.
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;
}
}
}
Esta expresión regular coincidirá con las direcciones IPv6 e IPv4 válidas de acuerdo con la implementación de GNU C ++ de expresiones regulares con el modo EXTENSO REGULAR utilizado:
"^/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*$"
Esto capta también el loopback (:: 1) y las direcciones ipv6. cambiado {} a + y puesto: dentro del primer corchete.
([A-f0-9:]+:+)+[A-f0-9]+
probado con ifconfig -a salida http://regexr.com/
La opción de terminal Unix o Mac OSx devuelve solo la salida coincidente (ipv6) incluyendo :: 1
ifconfig -a | egrep -o ''([A-f0-9:]+:+)+[A-f0-9]+''
Obtenga todas las direcciones IP (IPv4 o IPv6) e imprima la coincidencia en el término OSX de Unix
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]+)''
Esto es lo que se me ocurrió, usando un poco de lookahead y grupos nombrados. Esto es, por supuesto, solo IPv6, pero no debería interferir con patrones adicionales si desea agregar 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})
Esto funcionará para IPv4 e IPv6:
^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}/.){3}[0-9]{1,3})$
Genere el siguiente uso de python y funciona con el módulo re. Las afirmaciones de anticipación aseguran que la cantidad correcta de puntos o dos puntos aparezca en la dirección. No es compatible con IPv4 en notación 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)
Lo siguiente validará las direcciones IPv4, IPv6 (completa y comprimida) e IPv6v4 (completa y comprimida):
''/^(?>(?>([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''
No pude obtener la respuesta de @Factor Mystic para trabajar con expresiones regulares POSIX, así que escribí una que funciona con expresiones regulares POSIX y expresiones regulares PERL.
Debe coincidir:
- Direcciones IPv6
- cero direcciones IPv6 comprimidas ( sección 2.2 de rfc5952 )
- direcciones IPv6 de enlace local con índice de zona ( sección 11 de rfc4007 )
- Dirección IPv6 incrustada IPv4 ( sección 2 de rfc6052 )
- Direcciones IPv6 mapeadas IPv4 ( sección 2.1 de rfc2765 )
- Direcciones traducidas por IPv4 ( sección 2.1 de rfc2765 )
Expresión regular de 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]))
Para facilitar la lectura, la siguiente es la división de expresión regular anterior en los principales puntos OR en líneas separadas:
# 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])
Para hacer que lo anterior sea más fácil de entender, el siguiente código "pseudo" replica lo anterior:
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)
)
Publiqué un script en GitHub que prueba la expresión regular: https://gist.github.com/syzdek/6086792
No soy un experto en Ipv6 pero creo que puedes obtener un buen resultado más fácilmente con este:
^([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})$
para responder "es un ipv6 válido", me parece bien. Para dividirlo en partes ... olvídalo. He omitido el no especificado (:) ya que no tiene sentido tener "dirección no especificada" en mi base de datos.
el comienzo: ^([0-9A-Fa-f]{0,4}:){2,7}
<- coincide con la parte compresible, podemos traducir esto como: entre 2 y 7 puntos que pueden tener un número hexadecimal entre ellos.
seguido de: [0-9A-Fa-f]{1,4}$
<- un número hexadecimal (se omite 0) O ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/.|$)){4}
<- una dirección IPv4
Para usuarios de PHP 5.2+, filter_var
funciona muy bien.
Sé que esto no responde a la pregunta original (específicamente una solución de expresiones regulares), pero publico esto con la esperanza de que pueda ayudar a alguien más en el futuro.
$is_ip4address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE);
$is_ip6address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE);
Parece que puedes estar usando Python. Si es así, puedes usar algo como esto:
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
No creo que tenga que haber compilado IPv6 en Python para obtener inet_pton
, que también puede analizar las direcciones IPv4 si socket.AF_INET
como primer parámetro. Nota: esto puede no funcionar en sistemas que no sean Unix.
Puede usar las herramientas de shell ipextract que hice para este propósito. Se basan en expresiones regulares y grep.
Uso:
$ ifconfig | ipextract6
fe80::1%lo0
::1
fe80::7ed1:c3ff:feec:dee1%en0
Si puedo eludir su pregunta, considere usar la noción de dirección de la biblioteca de red para analizar y verificar si hay errores.
Me imagino que en algún momento querrás hacer algo con estas direcciones, así que ¿por qué no vas directamente a la fuente y te aseguras de que tu biblioteca de redes entienda la dirección? Esto es mejor que solo esperar que la expresión regular que se va a publicar aquí coincida con el concepto de la dirección de su implementación.
En Java tenemos InetAddress
. En .NET tenemos IPAddress
. En .NET, incluso tienes TryParse
en la clase IPAddress
para hacer esta prueba por ti.
bool IsIP6(string addr) {
IPAddress ip;
if (IPAddress.TryParse(addr, out ip)) {
return ip.AddressFamily == AddressFamily.InterNetworkV6;
}
else {
return false;
}
}
Si usa Perl, pruebe Net::IPv6Addr
use Net::IPv6Addr;
if( defined Net::IPv6Addr::is_ipv6($ip_address) ){
print "Looks like an ipv6 address/n";
}
use NetAddr::IP;
my $obj = NetAddr::IP->new6($ip_address);
use Validate::IP qw''is_ipv6'';
if( is_ipv6($ip_address) ){
print "Looks like an ipv6 address/n";
}
Simplemente haciendo coincidir los locales de un origen con corchetes incluidos. Sé que no es tan completo, pero en javascript los otros tenían problemas difíciles de rastrear, principalmente el de no funcionar, por lo que parece que me da lo que necesitaba por ahora. tampoco se necesitan AF de mayúsculas adicionales.
^/[([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 versión de Jinnko está simplificada y es mejor que yo vea.
Tendría que secundar fuertemente la respuesta de .
Mientras dices que necesitas una expresión regular para que coincida con una dirección IPv6, supongo que lo que realmente necesitas es poder comprobar si una cadena determinada es una dirección IPv6 válida. Aquí hay una distinción sutil pero importante.
Hay más de una forma de comprobar si una cadena determinada es una dirección IPv6 válida y la coincidencia de expresiones regulares es solo una solución.
Use una biblioteca existente si puede. La biblioteca tendrá menos errores y su uso dará como resultado menos código para que usted pueda mantener.
La expresión regular sugerida por es larga y compleja. Lo más probable es que funcione, pero también debería considerar cómo se las arreglaría si falla inesperadamente. El punto que intento hacer aquí es que si no puede formar una expresión regular requerida usted mismo no podrá depurarla fácilmente.
Si no tiene una biblioteca adecuada, puede ser mejor escribir su propia rutina de validación IPv6 que no dependa de expresiones regulares. Si lo escribe, lo comprende y, si lo entiende, puede agregar comentarios para explicarlo, de modo que otros también puedan comprenderlo y, luego, mantenerlo.
Actúe con precaución cuando use una expresión regular cuya funcionalidad no pueda explicarle a otra persona.
Una expresión regular simple que coincidirá, pero no recomendaría para la validación de ningún tipo es esta:
([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}
Tenga en cuenta que esto coincide con la compresión en cualquier parte de la dirección, aunque no coincidirá con la dirección de bucle invertido :: 1. Considero que este es un compromiso razonable para mantener la expresión regular simple.
Utilicé esto con éxito en las reglas de selección inteligentes de iTerm2 para hacer clic en cuatro direcciones IPv6.
InetAddressUtils
tiene todos los patrones definidos. Terminé usando su patrón directamente, y lo estoy pegando aquí como referencia:
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
Following regex is for IPv6 only. Group 1 matches with the IP.
(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})
Regexes for ipv6 can get really tricky when you consider addresses with embedded ipv4 and addresses that are compressed, as you can see from some of these answers.
The open-source IPAddress Java library will validate all standard representations of IPv6 and IPv4 and also supports prefix-length (and validation of such). Disclaimer: I am the project manager of that library.
Ejemplo de código:
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
}
The regex allows the use of leading zeros in the IPv4 parts.
Some Unix and Mac distros convert those segments into octals.
I suggest using 25[0-5]|2[0-4]/d|1/d/d|[1-9]?/d
as an IPv4 segment.
Try this small one-liner. It should only match valid uncompressed/compressed IPv6 addresses (no IPv4 hybrids)
/(?!.*::.*::)(?!.*:::.*)(?!:[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}/