m = re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",s)
如何修改它,使其不仅匹配 IPv4,还匹配 CIDR(如
10.10.10.0/24
)?
(?:\d{1,3}\.){3}\d{1,3}(?:/\d\d?)?
我在使用与您类似的正则表达式时遇到了问题。它匹配 1.2.3.4.5(如 1.2.3.4)和 1111.2.3.4(如 111.2.3.4)。为了避免匹配这些,我添加了前瞻/后瞻断言:
IP_RE = re.compile(r"(?<!\d\.)(?<!\d)(?:\d{1,3}\.){3}\d{1,3}(?!\d|(?:\.\d))")
IP_CIDR_RE = re.compile(r"(?<!\d\.)(?<!\d)(?:\d{1,3}\.){3}\d{1,3}/\d{1,2}(?!\d|(?:\.\d))")
(?<!\d\.)(?<!\d)
检查第一个八位字节之前没有数字或八位字节(即:111.2.3.4 之前没有 1)。
并且 (?!\d|(?:\.\d))
检查最后一个之后是否没有数字/八位字节(即:1.2.3.4 之后没有 .5)。
然后,要检查这些匹配的字符串是否是有效的 IP(例如:不是 277.1.1.1),您可以使用
socket.inet_aton(ip) #raises exception if IP is invalid
刚刚做了一个非常好的正则表达式,它还检查 ip 格式的正确性,不太长,并且可以选择匹配子网长度:
(25[0-5]|2[0-4]\d|1\d\d|\d\d|\d).(?1).(?1).(?1)\/?(\d\d)?
netaddr的ip模块中有一个
all_matching_cidrs(ip, cidrs)
函数;它需要一个 IP 并将其与 CIDR 地址列表进行匹配。
ReGex(带/不带 CIDR 的 ip_address)
试试这个:
str1 = '0.0.0.0/0'
str2 = '255.255.255.255/21'
str3 = '17.2.5.0/21'
str4 = '29.29.206.99'
str5 = '265.265.20.20'
pattern = r"^((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]?)([/][0-3][0-2]?|[/][1-2][0-9]|[/][0-9])?$"
def check_ip(user_input):
match = re.search(pattern, user_input)
if match:
print(f"Yes, IP-address {match.string} is correct")
else:
print("No, IP-address is incorrect")
check_ip(str1)
check_ip(str2)
check_ip(str3)
check_ip(str4)
check_ip(str5)
输出:
Yes, IP-address 0.0.0.0/0 is correct
Yes, IP-address 255.255.255.255/21 is correct
Yes, IP-address 17.2.5.0/21 is correct
Yes, IP-address 29.29.206.99 is correct
No, IP-address is incorrect
这扩展了你现有的表达方式
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\\\d{1,2}
追加
"(?:/\d{1,2})?"
。
这会让你
r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:/\d{1,2})?"
找到一个模式。
我找到的最佳答案是:
^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$