test_numb3rs.py检测到numb3rs.py仅校验IPv4首字节范围,预期退出码1而非0
IPv4地址校验函数仅校验第一个字节范围导致测试失败
test_numb3rs.py检测到numb3rs.py仅对IPv4地址的第一个字节进行范围校验,预期测试退出码为1,但实际得到0。尝试添加测试用例后仍报错,需要技术支持。
numb3rs.py代码
import re def main(): print(validate(str(input("IPv4 Address: ")))) def validate(ip): return bool(re.match(r"^(([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])$", ip)) if __name__ == "__main__": main()
test_numb3rs.py代码
from numb3rs import validate def test_max_min(): assert(validate("1.1.1.1")) == True assert(validate("255.255.255.255")) == True def test_alpha(): assert(validate("abc")) == False def test_incorrect_limit(): assert(validate("1000.1000.266.1000")) == False assert(validate("05.1c2.02.04")) == False assert(validate("5.1111.1.1")) == False assert(validate("1.1.1.1.1")) == False assert(validate("1.1.1..")) == False assert(validate("1.1000.1.1")) == False assert(validate("1000.1.1.1")) == False
问题分析与解决方案
你的正则表达式语法上看似正确,但可能因正则引擎的分组重复匹配逻辑,导致某些场景下未正确校验后续字节。更可靠的方式是放弃正则,改用拆分IP地址后逐个校验的方法,逻辑清晰且不易出错:
def validate(ip): # 拆分IP为四个部分 parts = ip.split('.') # 必须恰好四个部分 if len(parts) != 4: return False for part in parts: # 检查是否为纯数字 if not part.isdigit(): return False # 转换为整数校验范围 num = int(part) if num < 0 or num > 255: return False # 禁止前导零(如"05"这种不符合IPv4规范的格式) if len(part) > 1 and part.startswith('0'): return False return True
这个实现可以覆盖所有测试用例:
- 合法IP如"1.1.1.1"、"255.255.255.255"返回True
- 包含非数字、超出范围的字节、多余/缺失部分的IP均返回False
- 带前导零的字节(如"05")也会被拒绝
如果坚持使用正则,可以将重复分组改为明确的四个部分,避免引擎匹配歧义:
def validate(ip): pattern = r"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" return bool(re.fullmatch(pattern, ip))
这里改用re.fullmatch替代re.match,确保整个字符串完全匹配正则,避免部分匹配的问题。
内容的提问来源于stack exchange,提问作者Bryan Tamrin
相关产品推荐
相关产品推荐

