检查字符串是否与python中的IP地址模式匹配?

时间:2010-08-11 20:59:17

标签: python

检查字符串是否与某个模式匹配的最快方法是什么?正则表达式是最好的方法吗?

例如,我有一堆字符串,想要检查每一个字符串以查看它们是否是有效的IP地址(在这种情况下有效意味着正确的格式),是使用正则表达式执行此操作的最快方法吗?或者有更快的东西像字符串格式或其他东西。

这样的事情是我到目前为止所做的:

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

19 个答案:

答案 0 :(得分:71)

看起来你正试图validate IP addresses。正则表达式可能不是最好的工具。

如果您想接受所有有效的IP地址(包括您可能甚至不知道的某些地址有效),那么您可以使用IPy (Source)

from IPy import IP
IP('127.0.0.1')

如果IP地址无效,则会抛出异常。

或者你可以使用socket (Source)

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

如果你真的只想将IPv4与4个小数部分匹配,那么你可以在dot上分割并测试每个部分是0到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

请注意,您的正则表达式不会执行此额外检查。它会接受999.999.999.999作为有效地址。

答案 1 :(得分:14)

如果您使用 Python3 ,则可以使用ipaddress模块http://docs.python.org/py3k/library/ipaddress.html。示例:

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

答案 2 :(得分:13)

我通常是极少数坚持捍卫正则表达式的Python专家之一(他们在Python社区中声名狼借),但这不是其中之一 - 接受(比如说){{1因为“IP地址”真的不好,如果你需要在匹配RE之后做更多的检查,那么使用RE的大部分内容都会丢失。所以,我第二次@Mark的建议是:IPy一般性和优雅(如果你想要支持IPv6!),字符串操作和int检查,如果你只需要IPv4(但是,请三思而后行,然后再考虑再想一想 - IPv6的时间已经方式来了! - ):

'333.444.555.666'

我宁愿这样做而不是一个复杂的RE来匹配0到256之间的数字! - )

答案 3 :(得分:3)

再一次验证没有重新:

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)

答案 4 :(得分:2)

您的正则表达式不检查字符串的结尾,因此它将匹配:

123.45.67.89abc123boogabooga

要解决此问题,请使用:

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

(注意最后的$)。

最后,在Python中,通常的方式是使用is not None而不是!= None

答案 5 :(得分:2)

如果您要验证IP地址,我会建议以下内容:

import socket

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

如果您只是想检查它是否格式正确,那么您可能希望为所有legal bases(而不仅仅是基数10编号)执行此操作。

此外,仅IP地址是IPv4(并且没有IPv6),那么您可以查找有效地址并使用split()(以获取IP的各个组件)和int()(用于比较的种姓)。有效IPv4规则的快速参考是here

答案 6 :(得分:2)

安装netaddr软件包

sudo pip install netaddr

然后你可以这样做

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

此外,您还可以从该字符串创建一个IPAddress对象以及更多与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']

答案 7 :(得分:1)

如果你反复使用,你应该预编译正则表达式

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

然后使用

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

但是...... '111.222.333.444'真的是IP?

我会查看netaddripaddr个库是否可以用来匹配IP

答案 8 :(得分:1)

我们不需要任何导入来执行此操作。这也可以更快地运行

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

答案 9 :(得分:1)

此页面中的其他正则表达式答案将接受数字超过255的IP。

这个正则表达式可以避免这个问题:

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

答案 10 :(得分:0)

可以使用iptools。

import iptools
ipv4 = '1.1.1.1'
ipv6 = '5000::1'
iptools.ipv4.validate_ip(ipv4) #returns bool
iptools.ipv6.validate_ip(ipv6) #returns bool

答案 11 :(得分:0)

您可以尝试以下方法(该程序可以进一步优化):

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

答案 12 :(得分:0)

在Python 3.6上我觉得更简单,因为已经包含了ipaddress模块​​:

import ipaddress

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

答案 13 :(得分: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])

使用某个名称保存代码 - check_ip.py并将其作为python check_ip.py 192.168.560.25运行 注意: - 以上代码针对以下IP地址失败 -
023.65.029.33

答案 14 :(得分:0)

这也适用于ipv6地址。

不幸的是它仅适用于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')

答案 15 :(得分:0)

使用内置库 ipaddress 检查给定IP是否有效非常简单。您也可以使用掩码值进行验证。

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

注意:在Python 3.4.3中测试

答案 16 :(得分:0)

我作弊并使用了其他人提交的多个答案的组合。我认为这是非常明确和直接的代码。 ip_validation应该返回TrueFalse。此答案仅适用于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())

答案 17 :(得分:0)

你可以通过编译来加快它的速度:

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

答案 18 :(得分:-1)

您可以使用正则表达式:http://www.regular-expressions.info/python.html