使用正则表达式匹配IP地址

26

我正在尝试创建一个测试,以检查sys.argv输入是否匹配IP地址的正则表达式...

作为简单的测试,我有以下代码...

import re

pat = re.compile("\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}")
test = pat.match(hostIP)
if test:
   print "Acceptable ip address"
else:
   print "Unacceptable ip address"
然而,当我向它传递随机值时,在大多数情况下它会返回“可接受的IP地址”,除非我有一个与 \d+ 基本等效的“地址”。

5
你愿意将 999.999.999.999 视为“有效”的 IP 地址吗? :) - Maria Zverina
请查看以下链接:https://dev59.com/I3RC5IYBdhLWcg3wXP0C?lq=1 和 http://stackoverflow.com/questions/10191442/check-hostnames-and-ip-addresses-v4-and-v6-using-a-single-python-regex?rq=1 - belacqua
14个回答

47

使用正则表达式验证IP地址是一个不好的主意-这会将999.999.999.999作为有效值传递。尝试使用socket而不是这种方法-更好的验证方法,同样容易,甚至更容易实现。

import socket

def valid_ip(address):
    try: 
        socket.inet_aton(address)
        return True
    except:
        return False

print valid_ip('10.10.20.30')
print valid_ip('999.10.20.30')
print valid_ip('gibberish')

如果您真的想使用基于解析主机的方法,那么以下代码可以完全实现:

def valid_ip(address):
    try:
        host_bytes = address.split('.')
        valid = [int(b) for b in host_bytes]
        valid = [b for b in valid if b >= 0 and b<=255]
        return len(host_bytes) == 4 and len(valid) == 4
    except:
        return False

1
我也支持这种方法(大约一小时前点赞了:))。 - Levon
4
套接字方法使用 address='0.33' 时返回 true! - Ritesh
3
我会尽力进行翻译:@Maria - 我认为关键在于“匹配”IP地址,例如:“这是一个10TB的文件/数据库,请列出或者匹配可以找到的IP地址”,而不是“创建一个函数,接收一个字符串并返回它是否是一个IP地址”,因此我认为解决方案是使用一个精心制作的正则表达式,尽管我们非常讨厌它们。 - Speedbird
1
@Speedbird - OP指定在sys.argv中检查IP地址。因此,我认为正则表达式不是正确的选择。我同意,如果您需要处理大型文件/数据库,则正则表达式将是一个不错的选择。 :) - Maria Zverina
IPv6完全被忽略了。否则,套接字方法很好,但需要注意的是,在解析方法中,127.1被识别为无效IP,而它是有效的。 - 0xc0de
显示剩余5条评论

28

你需要按照以下方式修改你的正则表达式

pat = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")

那是因为 . 是一个通配符,代表着“任何字符”。


2
顺便提一下:在字符串前面加上 r,这是一个好习惯:r"^\d{1,3}..." - Ned Batchelder
5
伙计们,这不起作用..在给予“绿色的勾”之前请先测试它。255.255.255.256 失败了,依此类推.. - FrancescoN
2
这个不起作用。它还过滤了这个 - 2.16.840.1,这不可能是一个IP地址。 - Sheesh Mohsin
我们都知道ipv4将有三个“.”和4个数字,是否可能在这个正则表达式中简化为类似于pat = re.compile("^\d{1,3}(\.\d{1,3}){3}$")的东西? - ZDunker
3
它将匹配IPv4地址。它还将匹配看起来像IPv4地址但实际上不是的东西,因此它不是一个IPv4地址验证器。但是,在解析IPv4地址的地方(例如Apache日志文件),它仍然很有价值,因为目标是检索地址字段而不是验证它。 - President James K. Polk
显示剩余3条评论

16

IPv4的正则表达式:

^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

否则,您将获得无效的IP地址,例如999.999.999.999、256.0.0.0等


哇!我想我会坚持使用套接字方法,谢谢。不过我会记下来的……我一直在想它会是什么样子。 :-) - MHibbin
很好。如果不是使用Python而是PRCE,可以使用子程序使代码变得更短:^((25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}(?2)$https://regex101.com/r/sE3hK5/1 - Alexander Trakhimenok
我认为在第一组之后有一个错误。您在逃逸 \ 而不是点,并让它以任何类型的字符方式进行匹配。这里是我做出的修正: https://regexper.com/#%5E%28%2825%5B0-5%5D%7C2%5B0-4%5D%5B0-9%5D%7C%5B01%5D%3F%5B0-9%5D%5B0-9%5D%3F%29%5C.%29%7B3%7D%2825%5B0-5%5D%7C2%5B0-4%5D%5B0-9%5D%7C%5B01%5D%3F%5B0-9%5D%5B0-9%5D%3F%29%24 - NFSpeedy
这个看起来比正确答案好多了,但是带前导零的IP地址将会被错误地匹配,例如001.001.001.1,在一般的库中使用是无效的。 - cinatic

13

我遇到了相同的情况,我发现使用socket库的答案很有帮助,但它不支持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'))

这将返回0.0.0.0 - rakesh patanga
6
@rakeshpatanga,是的,这是一个有效的IP地址。 - Deepak
如果您的地址有前导零,例如192.168.007.001,则无法正常工作。如果您希望接受前导零,则最好使用正则表达式。 - user9645

3

您正在尝试使用“.”作为一个字符,而不是通配符。请使用\.来表示句号。


0
def ipcheck():
# 1.Validate the ip adderess
input_ip = input('Enter the ip:')
flag = 0

pattern = "^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$"
match = re.match(pattern, input_ip)
if (match):
    field = input_ip.split(".")
    for i in range(0, len(field)):
        if (int(field[i]) < 256):
            flag += 1
        else:
            flag = 0
if (flag == 4):
    print("valid ip")
else:
    print('No match for ip or not a valid ip')

0
re.sub('((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])', '--', '127.0.0.1')

使用这个正则表达式,只有0到255之间的数字可以组成地址。它还处理前导零,所以127.00.0.1将不会通过。


0
如果你真的想使用正则表达式,下面的代码可以过滤文件中的非有效 IP 地址,无论文件的组织方式如何,每行一个或多个,即使有更多文本(正则表达式的概念本身):
def getIps(filename):
    ips = []
    with open(filename) as file:
        for line in file:
            ipFound = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").findall(line)
            hasIncorrectBytes = False
            try:
                    for ipAddr in ipFound:
                        for byte in ipAddr:
                            if int(byte) not in range(1, 255):
                                hasIncorrectBytes = True
                                break
                            else:
                                pass
                    if not hasIncorrectBytes:
                        ips.append(ipAddr)
            except:
                hasIncorrectBytes = True

    return ips

0
import re
ipv=raw_input("Enter an ip address")
a=ipv.split('.')
s=str(bin(int(a[0]))+bin(int(a[1]))+bin(int(a[2]))+bin(int(a[3])))
s=s.replace("0b",".")
m=re.search('\.[0,1]{1,8}\.[0,1]{1,8}\.[0,1]{1,8}\.[0,1]{1,8}$',s)
if m is not None:
    print "Valid sequence of input"
else :
    print "Invalid input sequence"

为了让它简单明了,我使用了这种方法。所谓简单,是为了解释ipv4地址如何被评估。虽然检查它是否为二进制数并非必需。希望您喜欢。


0
str = "255.255.255.255"
print(str.split('.'))

list1 = str.split('.')

condition=0

if len(list1)==4:
    for i in list1:
        if int(i)>=0 and int(i)<=255:
            condition=condition+1

if condition!=4:
    print("Given number is not IP address")
else:
    print("Given number is valid IP address")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接