php正则匹配ipv4时019或256被误判,因常见正则仅校验数字位数而未严格限制每段0–255范围及禁止前导零;正确写法需分组匹配250–255、200–249、100–199、10–99、0,并用^和$锚定。

PHP正则匹配IPv4时为什么019或256会被误判为合法
因为多数人写的正则只管“是不是数字+点”,没严格约束每段的数值范围和前导零规则。比如\d{1,3}会匹配019(实际应拒绝)、256(超出255上限),甚至00、000这类带前导零的非法形式。
用preg_match()排除非法数值的关键写法
必须把每段拆解成互斥的合法区间,不能靠[0-9]{1,3}这种模糊匹配。正确分组逻辑是:
-
25[0-5]→ 覆盖 250–255 -
2[0-4][0-9]→ 覆盖 200–249 -
1[0-9]{2}→ 覆盖 100–199 -
[1-9][0-9]→ 覆盖 10–99(排除00–09里的前导零) -
0→ 单独允许0,但不允许00或01
组合成完整模式:/^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|0)\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|0)$/
常见错误写法及后果
这些正则看着短,但会在生产环境放行非法地址:
-
/^(\d{1,3}\.){3}\d{1,3}$/→ 允许999.999.999.999、01.01.01.01 -
/^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/→[01]?\d\d?会匹配019(0开头+两位数) - 漏掉
^和$→"192.168.1.1\n"或" 192.168.1.1 "也能过
比正则更稳的替代方案:用filter_var()加范围过滤
正则易错,PHP原生filter_var()更可靠,但默认不查前导零——filter_var("192.068.1.1", FILTER_VALIDATE_IP)会返回false(注意:它其实能识别068非法,但行为依赖PHP版本;7.4+已修复)。真正要保险,就组合使用:
- 先用
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)筛格式 - 再用
ip2long($ip) !== false确认可转为整数(自动拒绝前导零) - 若需排除私有/保留地址,补上
FILTER_FLAG_NO_PRIV_RANGE和FILTER_FLAG_NO_RES_RANGE
真正难的不是写出最长正则,而是意识到:IP校验常被当“小功能”跳过测试,结果上线后010.0.0.1悄悄绕过风控或日志归类——边界值永远在你没写测试用例的地方出问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











