python中的正则表达式-如何理解这个没有括号的ip标签
我使用以下代码检查字符串是否为有效的IPv4地址: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:
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”的吗?