with tutorial framework español djangoproject desde con cero applications python

python - framework - tutorial django



comprobar si una cadena coincide con un patrón de dirección IP en python? (18)

¿Cuál es la forma más rápida de verificar si una cadena coincide con un patrón determinado? Es regex la mejor manera?

Por ejemplo, tengo un montón de cadenas y quiero verificar cada una de ellas para ver si son una dirección IP válida (válida en este caso, es decir, el formato correcto), ¿es la forma más rápida de hacerlo usando expresiones regulares? O hay algo más rápido con el formato de cadenas similares o algo así.

Algo así es lo que he estado haciendo hasta ahora:

for st in strs: if re.match(''/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}'', st) != None: print ''IP!''


En Python 3.6 creo que es mucho más simple ya que el módulo ipaddress ya está incluido:

import ipaddress def is_ipv4(string): try: ipaddress.IPv4Network(string) return True except ValueError: return False


Esto también funciona para direcciones IPv6.

Desafortunadamente funciona solo para python3

import ipaddress def valid_ip(address): try: print ipaddress.ip_address(address) return True except: return False print valid_ip(''10.10.20.30'') print valid_ip(''2001:DB8::1'') print valid_ip(''gibberish'')


Hice trampa y usé la combinación de respuestas múltiples enviadas por otras personas. Creo que esto es una pieza bastante clara y directa de código. ip_validation debería devolver True o False . Además, esta respuesta solo funciona para direcciones IPv4

import re ip_match = re.match(''^'' + ''[/.]''.join([''(/d{1,3})'']*4) + ''$'', ip_input) ip_validate = bool(ip_match) if ip_validate: ip_validate &= all(map(lambda n: 0 <= int(n) <= 255, ip_match.groups())


Instalar el paquete netaddr

sudo pip install netaddr

Y luego puedes hacer esto

>>> from netaddr import valid_ipv4 >>> valid_ipv4(''11.1.1.2'') True >>> valid_ipv4(''11.1.1.a'') False

También creas un objeto IPAddress a partir de esa cadena y muchas más operaciones relacionadas con la ip

>>> from netaddr import IPAddress >>> ip = IPAddress(''11.1.1.1'') >>> [f for f in dir(ip) if ''__'' not in f] [''_module'', ''_set_value'', ''_value'', ''bin'', ''bits'', ''format'', ''info'', ''ipv4'', ''ipv6'', ''is_hostmask'', ''is_ipv4_compat'', ''is_ipv4_mapped'', ''is_link_local'', ''is_loopback'', ''is_multicast'', ''is_netmask'', ''is_private'', ''is_reserved'', ''is_unicast'', ''key'', ''netmask_bits'', ''packed'', ''reverse_dns'', ''sort_key'', ''value'', ''version'', ''words'']


Muy sencillo comprobar si la IP dada es válida o no en la biblioteca integrada ipaddress . También puede validar usando el valor de máscara .

ip = ''30.0.0.1'' #valid #ip = ''300.0.0.0/8'' #invalid #ip = ''30.0.0.0/8'' #valid #ip = ''30.0.0.1/8'' #invalid #ip = ''fc00:da00::3402:69b1'' #valid #ip = ''fc00:da00::3402:69b1/128'' #valid #ip = ''fc00:da00::3402:69b1:33333'' #invalid if ip.find(''/'') > 0: try: temp2 = ipaddress.ip_network(ip) print(''Valid IP network'') except ValueError: print(''Invalid IP network, value error'') else: try: temp2 = ipaddress.ip_address(ip) print(''Valid IP'') except ValueError: print(''Invalid IP'')

Nota: Probado en Python 3.4.3


No necesitamos ninguna importación para hacer esto. Esto también funciona mucho más rápido

def is_valid_ip(str_ip_addr): """ :return: returns true if IP is valid, else returns False """ ip_blocks = str(str_ip_addr).split(".") if len(ip_blocks) == 4: for block in ip_blocks: # Check if number is digit, if not checked before calling this function if not block.isdigit(): return False tmp = int(block) if 0 > tmp > 255: return False return True return False


Normalmente soy uno de los pocos expertos en Python que defiende firmemente las expresiones regulares (tienen una reputación bastante mala en la comunidad de Python), pero este no es uno de esos casos: aceptar (decir) ''333.444.555.666'' como una "dirección IP" es realmente mala, y si necesita hacer más comprobaciones después de hacer coincidir el RE, gran parte del punto de utilizar un RE se pierde de todos modos. Por lo tanto, IPy las recomendaciones de IPy : generalidad y elegancia (¡incluido el soporte de IPv6 si lo desea!), Operaciones de cadena y verificaciones int si solo necesita IPv4 (pero, piense dos veces sobre esa limitación, y luego piense una más - - ¡Ha llegado el momento de IPv6! -):

def isgoodipv4(s): pieces = s.split(''.'') if len(pieces) != 4: return False try: return all(0<=int(p)<256 for p in pieces) except ValueError: return False

Prefiero hacer eso que un RE enrevesado para hacer coincidir solo números entre 0 y 256! -)


Otras respuestas de expresiones regulares en esta página aceptarán una IP con un número superior a 255.

Esta expresión regular evitará este problema:

import re def validate_ip(ip_str): reg = r"^(([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])$" if re.match(reg, ip_str): return True else: return False


Parece que estás intentando validar las direcciones IP . Una expresión regular probablemente no sea la mejor herramienta para esto.

Si desea aceptar todas las direcciones IP válidas (incluidas algunas direcciones que probablemente ni siquiera sabía que eran válidas), entonces puede usar IPy (Source) :

from IPy import IP IP(''127.0.0.1'')

Si la dirección IP no es válida arrojará una excepción.

O podría usar socket (Source) :

import socket try: socket.inet_aton(addr) # legal except socket.error: # Not legal

Si realmente desea coincidir con IPv4 con 4 partes decimales, puede dividir el punto y probar que cada parte es un número entero entre 0 y 255.

def validate_ip(s): a = s.split(''.'') if len(a) != 4: return False for x in a: if not x.isdigit(): return False i = int(x) if i < 0 or i > 255: return False return True

Tenga en cuenta que su expresión regular no hace esta comprobación adicional. Aceptaría 999.999.999.999 como una dirección válida.


Puede hacerlo un poco más rápido compilando:

expression = re.compile(''^/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}$'') for st in strs: if expression.match(st): print ''IP!''


Puede intentar lo siguiente (el programa puede optimizarse aún más):

path = "/abc/test1.txt" fh = open (path, ''r'') ip_arr_tmp = [] ip_arr = [] ip_arr_invalid = [] for lines in fh.readlines(): resp = re.search ("([0-9]+).([0-9]+).([0-9]+).([0-9]+)", lines) print resp if resp != None: (p1,p2,p3,p4) = [resp.group(1), resp.group(2), resp.group(3), resp.group(4)] if (int(p1) < 0 or int(p2) < 0 or int(p3) < 0 or int(p4) <0): ip_arr_invalid.append("%s.%s.%s.%s" %(p1,p2,p3,p4)) elif (int(p1) > 255 or int(p2) > 255 or int(p3) > 255 or int(p4) > 255): ip_arr_invalid.append("%s.%s.%s.%s" %(p1,p2,p3,p4)) elif (len(p1)>3 or len(p2)>3 or len(p3)>3 or len(p4)>3): ip_arr_invalid.append("%s.%s.%s.%s" %(p1,p2,p3,p4)) else: ip = ("%s.%s.%s.%s" %(p1,p2,p3,p4)) ip_arr_tmp.append(ip) print ip_arr_tmp for item in ip_arr_tmp: if not item in ip_arr: ip_arr.append(item) print ip_arr



Si está validando la dirección IP, sugeriría lo siguiente:

import socket try: socket.inet_aton(addr) return True except socket.error: return False

Si solo quieres comprobar si está en el formato correcto, entonces querrás hacerlo para todas las bases legales (no solo para la numeración de base 10).

Además, si la dirección IP es solo IPv4 (y ninguna es IPv6), entonces podría buscar las direcciones válidas y usar split() (para obtener componentes individuales de la IP) e int() (para la casta de tipos para comparar) . Una referencia rápida a las reglas válidas de IPv4 está here .


Si usa Python3 , puede usar el módulo ipaddress http://docs.python.org/py3k/library/ipaddress.html . Ejemplo:

>>> import ipaddress >>> ipv6 = "2001:0db8:0a0b:12f0:0000:0000:0000:0001" >>> ipv4 = "192.168.2.10" >>> ipv4invalid = "266.255.9.10" >>> str = "Tay Tay" >>> ipaddress.ip_address(ipv6) IPv6Address(''2001:db8:a0b:12f0::1'') >>> ipaddress.ip_address(ipv4) IPv4Address(''192.168.2.10'') >>> ipaddress.ip_address(ipv4invalid) Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/lib/python3.4/ipaddress.py", line 54, in ip_address address) ValueError: ''266.255.9.10'' does not appear to be an IPv4 or IPv6 address >>> ipaddress.ip_address(str) Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/lib/python3.4/ipaddress.py", line 54, in ip_address address) ValueError: ''Tay Tay'' does not appear to be an IPv4 or IPv6 address


Su expresión regular no comprueba el final de la cadena, por lo que coincidiría:

123.45.67.89abc123boogabooga

Para arreglar esto, usa:

''/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}$''

(tenga en cuenta los $ al final).

Finalmente, en Python, el estilo habitual es usar is not None lugar de != None .


Una validación más sin re:

def validip(ip): return ip.count(''.'') == 3 and all(0<=int(num)<256 for num in ip.rstrip().split(''.'')) for i in (''123.233.42.12'',''3234.23.453.353'',''-2.23.24.234'',''1.2.3.4''): print i,validip(i)


debe precompilar la expresión regular, si la usa repetidamente

re_ip = re.compile(''/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}$'') # note the terminating $ to really match only the IPs

luego usa

if re_ip.match(st): print ''!IP''

pero ... ¿es por ejemplo ''111.222.333.444'' realmente el IP?

ipaddr bibliotecas netaddr o ipaddr si se pueden usar para hacer coincidir las direcciones IP


#!/usr/bin/python import sys def check_ip(address): part=address.split(".") temp=True if len(part) != 4: temp=False return temp for p in part: if not 0<= int(p) <= 255: temp=False return temp else: temp=True return temp if __name__=="__main__": print check_ip(sys.argv[1])

Guarde el código con un nombre que check_ip.py y ejecútelo como python check_ip.py 192.168.560.25
Nota: - El código anterior falla para la siguiente dirección IP-
023.65.029.33