2010-08-11 7 views
27

Wie kann man am schnellsten prüfen, ob eine Zeichenfolge mit einem bestimmten Muster übereinstimmt? Ist Regex der beste Weg?Überprüfen Sie, ob eine Zeichenfolge mit einem IP-Adressmuster in Python übereinstimmt.

Zum Beispiel habe ich eine Reihe von Zeichenfolgen und möchte überprüfen, ob sie eine gültige IP-Adresse sind (gültig in diesem Fall bedeutet korrekte Format), ist der schnellste Weg, dies mit Regex zu tun? Oder gibt es etwas schnelleres mit einer ähnlichen Formatierung von Strings oder so etwas?

So etwas ist, was ich bisher getan:

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

Antwort

58

Es ist wie Sie validate IP addresses versuchen aussieht. Ein regulärer Ausdruck ist wahrscheinlich nicht das beste Werkzeug dafür.

Wenn Sie alle gültigen IP-Adressen (einschließlich einiger Adressen, die Sie wahrscheinlich nicht einmal wissen, gültig waren) annehmen möchten, dann können Sie verwenden IPy(Source):

from IPy import IP 
IP('127.0.0.1') 

Wenn die IP-Adresse ungültig ist, wird es eine Ausnahme auslösen

Oder könnten Sie socket(Source):

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

Wenn Sie wirklich nur IPv4 Teile mit 4 Nachkommastellen wollen übereinstimmen, dann können Sie auf Punkt und Test aufgeteilt, dass jeder Teil eine ganze Zahl zwischen 0 und 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 

Beachten Sie, dass Ihr regulärer Ausdruck diese zusätzliche Überprüfung nicht durchführt. Es würde 999.999.999.999 als gültige Adresse akzeptieren.

+0

Hmmm das ist perfekt. Ja, ich dachte nicht über ganze Zahlen größer als 255 nach. –

+0

Nicht alle IP-Adressen sind dezimal. –

+0

Akzeptieren Sie dies für die IPy. Ich benutzte IPy teilweise wegen @ Alex IPv6-Punkt. –

2

Ihr regulärer Ausdruck überprüft nicht für das Ende des Strings, so würde es passen:

123.45.67.89abc123boogabooga 

Zur Behebung dieses verwenden:

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

(beachten Sie die $ am Ende).

Schließlich ist in Python der übliche Stil, is not None statt != None zu verwenden.

0

Sie können es ein wenig schneller machen, indem sie kompilieren:

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!' 
1

Sie die regexp vorkompilieren sollten, wenn Sie es immer wieder

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 

verwenden dann

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

aber .. ist zB '111.222.333.444' wirklich die IP?

i bei netaddr oder ipaddr Bibliotheken aussehen würde, ob sie verwendet werden können IPs entsprechen

11

Ich bin normalerweise die eines der sehr wenigen Python Experten, die sich standhaft reguläre Ausdrücke verteidigt (sie haben einen ziemlich schlechten Ruf in die Python-Community), aber das ist nicht einer dieser Fälle - akzeptieren (sagen) '333.444.555.666' als "IP-Adresse" ist wirklich schlecht, und wenn Sie mehr Prüfungen nach dem Abgleich der RE, viel von dem Sinn des tun müssen mit einem RE ist sowieso verloren. Also, ich zweiten @ Marks Empfehlungen herzlich: IPy für die Allgemeinheit und Eleganz (einschließlich der Unterstützung von IPv6, wenn Sie wollen!), String-Operationen und int prüft, ob Sie nur IPv4 brauchen (aber zweimal über diese Einschränkung nachdenken, und dann eine weitere denken - - IPv6 Zeit hat Weg kommen -):

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 

ich würde viel lieber tun, als ein gewundener RE nur Zahlen zwischen 0 und 256 übereinstimmen -)

+0

+1 für die Verwendung von 'a <= x

+0

Obwohl ich dem Hauptpunkt Ihrer Antwort vollkommen zustimme, überprüft der hier angegebene Code nur die Länge 4, während Adressen wie 127.1 gültig sind (socket.inet_aton stimmt überein, und diese Adressen können gepingt werden). Dies verstärkt die Notwendigkeit, IPy- oder Sockelmodule zu verwenden. – 0xc0de

1

Wenn Sie IP validieren! Adresse Ich würde folgendes vorschlagen:

import socket 

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

Wenn Sie nur überprüfen möchten, ob es im richtigen Format ist, dann sollten Sie es für alle legal bases (nicht nur Basis 10 Nummerierung) tun.

Auch sind die IP-Adresse nur IPv4 (und keine sind IPv6), dann können Sie sehen nur, was gültige Adresse und verwenden split() (um einzelne Komponenten des IP) und int() (typ Kaste für Vergleich). Eine kurze Referenz zu gültigen IPv4-Regeln ist here.

3

Eine weitere Validierung ohne 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) 
+0

Methoden wie diese sollten versucht werden, bevor Sie in 're' zurückkehren. – Dave

0

ich betrogen und von anderen Menschen vorgelegte Kombination aus mehreren Antworten verwendet. Ich denke, das ist ziemlich klar und geradlinig Stück Code. ip_validation sollte True oder False zurückgeben. Auch nur diese Antwort arbeitet für 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()) 
7

Adressen Wenn Sie Python3 verwenden, können Sie ipaddress-Modul http://docs.python.org/py3k/library/ipaddress.html verwenden. Beispiel:

>>> 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 
1

installieren netaddr Paket

sudo pip install netaddr 

und dann können Sie dies tun

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

Sie sich auch ein IPAddress-Objekt aus dieser Zeichenfolge erstellen und vieles mehr ip bezogenen Operationen

>>> 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'] 
1

Wir nicht brauche dazu einen Import.Dies funktioniert auch viel schneller

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 
0

Sehr einfach zu überprüfen, ob bestimmte IP gültig ist oder nicht ipaddress eingebaute Bibliothek. Sie können auch validieren mit Maske Wert.

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

Hinweis: Getestet in Python 3.4.3

0

Dies auch für IPv6-Adressen funktioniert.

Leider funktioniert es für python3 nur

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') 
0

Andere regex Antworten auf dieser Seite eine IP mit einer Nummer über 255

Diese Regex akzeptieren dieses Problem vermeiden:

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 
0
#!/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]) 

Speichern Sie den Code mit einem Namen say- check_ip.py und führen Sie es als python check_ip.py 192.168.560.25
Hinweis: - Above Code nicht für die untenstehende IP Adressen-
023.65.029.33

+0

Funktioniert dieser Code unter Windows? 'Datei" C: \ Python \ Codes \ check_ip.py ", Zeile 17 Drucken check_ip (sys.argv [1]) ^ SyntaxError: ungültige Syntax' – Sabrina

Verwandte Themen