Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的正则表达式-如何理解这个没有括号的ip标签_Python_Regex - Fatal编程技术网

python中的正则表达式-如何理解这个没有括号的ip标签

python中的正则表达式-如何理解这个没有括号的ip标签,python,regex,Python,Regex,我使用以下代码检查字符串是否为有效的IPv4地址: import re def is_ip4(IP): label = "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" pattern = re.compile("(" + label + "\.){3}" + label + "$") if pattern.match(IP): print("matched!") else:

我使用以下代码检查字符串是否为有效的IPv4地址:

import re

def is_ip4(IP):
    label = "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
    pattern = re.compile("(" + label + "\.){3}" + label + "$")
    if pattern.match(IP):
        print("matched!")
    else:
        print("No!")
它很好用。但是如果我从标签上去掉括号,如下所示

import re

def is_ip4(IP):
    label = "[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"
    pattern = re.compile("(" + label + "\.){3}" + label + "$")
    if pattern.match(IP):
        print("matched!")
    else:
        print("No!")

它显示了适用于
“2090.1.11.0”
“20.1.11.0”
,但不适用于
“2.1.11.0”
。事实上,我对有vs而没有括号的情况有点困惑。有人能给我解释一下吗?谢谢

之所以需要括号,是因为您使用了两步流程。括号本身不起任何作用(除了在组中捕获)。但你也在这样做:

pattern = re.compile("(" + label + "\.){3}" + label + "$")
标签
正则表达式复制两次,首先重复三次,然后是一个句点。该副本很好(几乎),因为在语句中,它再次被括在括号中。但是,第二个副本不在任何括号内,因此您将得到一个类似正则表达式(简化)的结果:

如果
(a | ab | abc\){3}a
匹配,或
ab
abc
匹配,则此项匹配。加上括号,它将类似于:

pattern == '((a|ab|abc)\.){3}(a|ab|abc)$'
因此,尽管括号显得多余,但并非出于两个原因。它们将时段与最后一个选项分开
abc
,并将最终选项与第一位分开

然而,你一开始就不应该这么做。只需使用:

from ipaddress import ip_address

def is_ip4(ip):
    try:
        ip_address(ip)
        return True
    except ValueError:
        return False
无需安装,这是一个标准库

您获得与
'2090.1.11.0'
匹配的原因是将其与此匹配:

'([0-9]|[1-9][0-9]|1[0-9][0-9]|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]$'
'([0-9]){3}[0-9]'
归结为将其与此匹配:

'([0-9]|[1-9][0-9]|1[0-9][0-9]|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]$'
'([0-9]){3}[0-9]'
因为,
[0-9]
是括号中“或”表达式的第一个选项,重复了三次,第二个
[0-9]
{3}
之后的“或”表达式的第一个选项

请注意,您为确保整个字符串匹配而输入的
$
与final'or'选项集中在一起,因此在这里不起任何作用

尝试运行以下命令,并注意相同的第一个匹配项:

import re

print(re.findall('([0-9]|[1-9][0-9]|1[0-9][0-9]|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]$', '2090.1.11.0'))
print(re.findall('([0-9]){3}[0-9]', '2090.1.11.0'))

(忽略第一行的第二个匹配项,不太相关)

如果您使用的是Python 3.3或更高版本,那么您可以使用该库来验证IP地址!我仍然不完全清楚为什么在这种情况下匹配“2090.1.11.0”(没有括号)。你能详细说明一下后一个正则表达式是如何匹配“2090.1.11.0”的吗?