Patrones1 caza jugable incluida

Regex para direcciones IPv4: de 0 a 255 como es debido

Una dirección IPv4 son cuatro números de 0 a 255. Por qué el patrón obvio con \d{1,3} deja pasar 999.999.999.999, cómo describir un octeto con alternancia, qué hacer con los ceros a la izquierda y cómo encontrar direcciones dentro de un texto.

Logo de Regex Hunter

· 7 min de lectura · Actualizado el

/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/

atrapa

  • 0
  • 42
  • 199
  • 255

deja libre

  • 256
  • 300
  • 07
  • 1000

Una dirección IPv4 son cuatro números separados por puntos, como 192.168.1.1. Cada número se llama octeto y va de 0 a 255.

Parece fácil de reconocer, y el primer patrón que escribe casi todo el mundo es corto y está mal. Este artículo empieza por ahí, lo corrige paso a paso y termina con un patrón para encontrar direcciones dentro de un texto. Todos los ejemplos son interactivos, así que edita los patrones y mira cómo cambian las líneas.

Respuesta rápidaJavaScript
/^((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)$/

Cuatro números del 0 al 255 separados por puntos, sin ceros a la izquierda.

Acepta

  • 192.168.1.1
  • 10.0.0.1
  • 255.255.255.0

Rechaza

  • 256.1.1.1
  • 010.0.0.1
  • 1.2.3

01El patrón obvio

Cuatro grupos de uno a tres dígitos, separados por puntos:

Coincidencias6/6 como se esperaba
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/

Debe coincidir4/4

  • 192.168.1.1
  • 8.8.8.8
  • 999.999.999.999
  • 300.1.2.3

No debe2/2

  • 1.2.3
  • 1.2.3.4.5
Pruébalo en la Zona de pruebas
La forma es correcta, pero \d{1,3} significa “cualquier número de 0 a 999”. Las dos últimas líneas no son direcciones reales.

Sí detecta un número incorrecto de partes. Y si estás revisando logs de confianza, puede que no necesites más. Pero como validador acepta cualquier cosa hasta 999.

La repetición puede ser más corta. Tres octetos terminan en punto, así que agrupa “octeto más punto” y repítelo tres veces con {3}:

Patrón23 car.
/^(\d{1,3}\.){3}\d{1,3}$/
Pruébalo en la Zona de pruebas
El mismo patrón que el de arriba. El grupo (\d{1,3}\.) aparece tres veces y luego un último octeto sin punto detrás.

02No olvides la barra invertida

En un patrón, un . suelto significa “cualquier carácter”. Quita las barras invertidas y los puntos dejan de significar puntos:

Coincidencias3/3 como se esperaba
/^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$/
  • 1.2.3.4
  • 1a2b3c4
  • 1234567
Pruébalo en la Zona de pruebas
Las dos últimas líneas coinciden. Los puntos sin escapar aceptan letras, e incluso dígitos.

1234567 es la más traicionera. Cada . coincide con un dígito, así que el patrón la lee como 1, 3, 5, 7 con 2, 4, 6 haciendo de “puntos”.

03Un octeto, de 0 a 255

Una regex no tiene ni idea de lo que vale un número. Solo ve caracteres. Así que “de 0 a 255” hay que escribirlo como reglas de texto, dividido en rangos que tengan cada uno una forma sencilla:

Rango Patrón Se lee como
250–255 25[0-5] 25, luego de 0 a 5
200–249 2[0-4]\d 2, luego de 0 a 4, luego cualquier dígito
100–199 1\d\d 1, luego dos dígitos cualesquiera
0–99 [1-9]?\d un 1 a 9 opcional, luego cualquier dígito

Únelos con | y mételos en un grupo:

Coincidencias10/10 como se esperaba
/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/

Debe coincidir6/6

  • 0
  • 9
  • 42
  • 199
  • 249
  • 255

No debe4/4

  • 256
  • 300
  • 07
  • 1000
Pruébalo en la Zona de pruebas
Cada rama cubre un rango. 256 falla en las cuatro: 25[0-5] llega hasta 5, 2[0-4]\d necesita de 0 a 4 en medio, 1\d\d necesita un 1 delante y [1-9]?\d tiene como mucho dos dígitos.

04Ceros a la izquierda

Fíjate en la última rama: [1-9]?\d, no \d{1,2}. Eso es lo que rechaza 07 y 010. Un octeto de dos dígitos tiene que empezar por 1 a 9.

Esto importa más de lo que parece. Algunas herramientas leen un cero a la izquierda como un número en octal. socket.inet_aton de Python, que sigue las antiguas reglas de red de C, convierte 010.0.0.1 en 8.0.0.1, porque 10 en octal es 8. Si una parte de tu sistema lee 010 como diez y otra como ocho, no se ponen de acuerdo sobre de qué dirección hablan. Rechazar los ceros a la izquierda evita la cuestión por completo.

05El patrón completo

Pon el grupo del octeto donde antes estaba \d{1,3}:

Coincidencias10/10 como se esperaba
/^((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)$/

Debe coincidir4/4

  • 0.0.0.0
  • 10.0.0.1
  • 192.168.1.1
  • 255.255.255.0

No debe6/6

  • 256.1.1.1
  • 192.168.1.300
  • 999.999.999.999
  • 010.0.0.1
  • 1.2.3
  • 1.2.3.4.5
Pruébalo en la Zona de pruebas
Tres grupos de “octeto y punto” y luego un octeto final. Cada octeto tiene que estar entre 0 y 255, sin ceros a la izquierda.

Es largo, pero es largo porque el octeto aparece dos veces, no porque sea complicado. Esto es lo que ahorra el {3} frente a escribir el octeto cuatro veces:

Comparación46 % más corto

Tablero0.0.0.0 · 10.0.0.1 · 192.168.1.1 · 255.255.255.0 · 8.8.4.4 vs 256.1.1.1 · 10.0.0 · 1.2.3.4.5 · 192.168.1.300 · 010.0.0.1

  1. escrito enterolo resuelve140
    /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/
  2. con un grupolo resuelve75
    /^((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)$/
Probar el más corto
Las dos versiones resuelven el tablero. El grupo con {3} ocupa 75 caracteres; la versión escrita entera, 140.

06Encontrar direcciones dentro de un texto

^ y $ solo sirven cuando toda la entrada es una dirección. Para encontrar direcciones en una línea de log, lo habitual es cambiarlos por límites de palabra, \b. Casi funciona:

Coincidencias3/3 como se esperaba
/\b((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)\b/

Debe coincidir2/2

  • server at 10.0.0.1.
  • version 1.2.3.4.5

No debe1/1

  • error 999.1.1.1
Pruébalo en la Zona de pruebas
La segunda línea es un número de versión, no una dirección, y aun así coincide. Un punto no es un carácter de palabra, así que hay un límite entre el 4 y el .5.

Lo que de verdad quieres es “ningún dígito ni punto justo antes, y nada más de dirección justo después”. Eso es trabajo para los lookarounds:

Coincidencias5/5 como se esperaba
/(?<![\d.])((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)(?!\.?\d)/

Debe coincidir2/2

  • server at 10.0.0.1.
  • ping 8.8.8.8 now

No debe3/3

  • version 1.2.3.4.5
  • error 999.1.1.1
  • build 1.2.3
Pruébalo en la Zona de pruebas
(?<![\d.]) dice que antes no hay ningún dígito ni punto. (?!\.?\d) dice que después no hay ningún dígito, ni un punto seguido de un dígito. Un punto final de frase sigue estando permitido.

Este también funciona con el re de Python. Python solo admite lookbehind de ancho fijo, y (?<![\d.]) siempre comprueba exactamente un carácter.

07O usa un parser

Si estás validando entradas en código, la biblioteca estándar ya lo hace. En Python:

import ipaddress

ipaddress.ip_address("192.168.1.1")             # IPv4Address('192.168.1.1')
ipaddress.ip_address("192.168.1.1").is_private  # True
ipaddress.ip_address("256.1.1.1")               # ValueError

Desde Python 3.9.5, ipaddress también rechaza ceros a la izquierda como 010.0.0.1. En Node, net.isIPv4("010.0.0.1") también es false, y da las mismas respuestas que el patrón completo de arriba en todos los ejemplos de este artículo. Un parser además se ocupa de IPv6, que es una regex mucho más grande.

08Pruébalo

El corazón de todo el patrón es el octeto. ¿Puedes escribirlo de memoria?

Caza jugablepar 35

Atrapa los números de 0 a 255 y deja libre todo lo demás.

Objetivos · 0/10 atrapados

  • 0objetivo
  • 7objetivo
  • 42objetivo
  • 99objetivo
  • 100objetivo
  • 199objetivo
  • 200objetivo
  • 249objetivo
  • 250objetivo
  • 255objetivo

Inocentes · 0 errores

  • 256inocente
  • 260inocente
  • 300inocente
  • 999inocente
  • 1000inocente
  • 07inocente
  • 007inocente

Escribe una regex: el tablero se actualiza mientras escribes.

Pruébalo en la Zona de pruebas
¿Te gustó? Cada día llega una nueva.Jugar la caza de hoy

09Lista de comprobación

  • \d{1,3} admite de 0 a 999. Usa (25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d) para un octeto.
  • Escapa todos los puntos: \..
  • Repite con un grupo: (octet\.){3}octet.
  • Usa [1-9]?\d para los números pequeños, así se rechazan los ceros a la izquierda.
  • Dentro de un texto, usa (?<![\d.]) y (?!\.?\d) en lugar de \b.
  • En código, mejor ipaddress (Python) o net.isIPv4 (Node).

10Sigue practicando