我无法解决正则表达式,我不知道是啥问题[重复]

Posted

技术标签:

【中文标题】我无法解决正则表达式,我不知道是啥问题[重复]【英文标题】:I cannot work regular expressions out, i don't know what is a problem [duplicate]我无法解决正则表达式,我不知道是什么问题[重复] 【发布时间】:2020-03-24 11:07:51 【问题描述】:

我正在尝试编写代码来使用正则表达式确定 ipv4 地址是否正确,但我似乎无法找出问题所在。

import re
pattern=re.compile('([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][0-9]|2[0-4][0-9]|25[0-5])')
ip=['17.255.16.45','255.255.255.255','0.0.0.0','0.14.255.14','2555.2564.0.3','0.3.255']

for i in range (len(ip)):
    if re.search(pattern,ip[i]):
        print(ip[i],'ok')
    else:
        print(ip[i],"nope")

【问题讨论】:

查看这个正则表达式测试器:regex101.com 这是一项勇敢的努力,但我认为您可能在这里对正则表达式施加了过多的负担。如果您想对格式严格要求,我会使用正则表达式来确保数字不以零开头(除非它只有 0),然后稍后在代码中检查值是否正常(问题本身仍然有效不过)。 正则表达式很酷,而且很好学 - 但这是重新发明***,还有一个“XY”问题:您需要验证 IP 的字符串,而不是“修复正则表达式” 【参考方案1】:

我认为问题在于您的\. 包含在交替中,而它应该始终包含在它之前的任何选项之后。您只需将这些选项放在一对括号中即可修复它。此外,建议使用raw strings 进行正则表达式以避免转义问题。

import re
pattern=re.compile(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][0-9]|2[0-4][0-9]|25[0-5])')
ip=['17.255.16.45','255.255.255.255','0.0.0.0','0.14.255.14','2555.2564.0.3','0.3.255']

for i in range (len(ip)):
    if re.search(pattern,ip[i]):
        print(ip[i],'ok')
    else:
        print(ip[i],"nope")

输出:

17.255.16.45 ok
255.255.255.255 ok
0.0.0.0 ok
0.14.255.14 ok
2555.2564.0.3 nope
0.3.255 nope

【讨论】:

【参考方案2】:

我什至不知道出了什么问题,但是一旦我将其重构为 这似乎有效:

import re

ip_num_pat = r"[0-9]|[1-9][0-9]|1[0-9]2|2[0-4][0-9]|25[0-5]"

pattern = re.compile(r'(?:(0)\.)3(0)'.format(ip_num_pat))
ip_addrs = [
    '17.255.16.45', '255.255.255.255', '0.0.0.0', '0.14.255.14',
    '2555.2564.0.3', '0.3.255']

for ip in ip_addrs:
    if pattern.match(ip):
        print(ip, 'ok')
    else:
        print(ip, 'nope')

一般来说,通过破坏它们可以更容易地跟踪此类事情 分成更小的部分。我认为可能最后一个块是错误的。

另外,请注意,我已将您的代码更改为使用 .match,而不是 .search。 这很关键,否则你会匹配到 01.2.3.4 这样的东西。

但是,正如其他人所说,更简单的方法如下所示:

ip_addrs = [
    '17.255.16.45', '255.255.255.255', '0.0.0.0', '0.14.255.14',
    '2555.2564.0.3', '0.3.255', '03.1.2.3']

def is_ip(addr):
    try:
        component_strings = addr.split(".")
        if any(i.startswith("0") and i != "0" for i in component_strings):
            raise ValueError("Components cannot start with 0")
        components = [int(i) for i in component_strings]
        if len(components) != 4:
            raise ValueError("Need 4 parts for an IPv4 address")
        if any(not 0 <= i < 256 for i in components):
            raise ValueError("Components should be in range 0, ..., 255")
        return True
    except ValueError:
        return False

for ip in ip_addrs:
    if is_ip(ip):
        print(ip, 'ok')
    else:
        print(ip, 'nope')

【讨论】:

【参考方案3】:

虽然出于教育目的使用正则表达式可能很有趣,但如果打算将其放入实际代码中,则最好使用 Python 的 ipaddress 模块 - 而不是重新发明***。

它是part of Python standard library since Python 3.3,使用它只需:

import ipaddress

# The "for ... in range(len(...))" pattern is not really needed in Python
# the native for can walk your sequence elements:
for address in ip:
    try:
       ipaddress.ip_address(address)
    except ValueError:
       print(address, "Nope")
    else:
       print (adress, "ok")

除了正则表达式中的细微错误之外,明显的优点是它还可以解析 IPv6 地址(如果不需要,可以在 .version 属性中轻松检查协议) - 上面的 ip_address 调用返回一个对象,该对象免费提供有关 IP 的大量信息,无需任何额外工作,包括但不限于:

 'is_link_local',
 'is_loopback',
 'is_multicast',
 'is_private',
 'is_reserved',
 'is_unspecified',
 'max_prefixlen',

【讨论】:

以上是关于我无法解决正则表达式,我不知道是啥问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章

我在字符串上有几个 preg_replace 未知修饰符警告,但我不知道正则表达式修复 [重复]

.* 到底是啥?在正则表达式中做? “.*?([a-m/]*).*” [重复]

有关Java中正则表达式的疑问[重复]

MySQL正则表达式搜索和替换[重复]

为啥我不能使用正则表达式来评估 if...else 语句 [重复]

只接受数字(0-9)和无字符的正则表达式[重复]