IPv4 校验正则与取值范围
IPv4 是四段 0 到 255 的十进制数,用点分隔。只写 \d{1,3} 会放过 999、256 这类不存在的段值,正确做法是按数值区间逐段表达:每段可写为 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d,再用整串锚定。正则只能校验形状,至于这个地址能否实际使用(是否私有、是否保留、是否与本机同网段)属于语义判断,要用地址库处理。
基本信息
| 每段范围 | 0 到 255,共四段,用点分隔 |
|---|---|
| 推荐写法 | 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d,四个分支从宽到窄排列 |
| 必须锚定 | 整串匹配要加 ^…$,或使用引擎的整串匹配接口 |
| 语义判断 | 私有段、环回、链路本地、广播等要靠代码按前缀判断,正则不做这件事 |
典型使用场景
- 配置项校验:填写服务器地址、监听地址时先挡掉明显错误的输入
- 日志字段提取:从访问日志里抽出客户端地址并统计来源分布
- 输入框即时提示:在提交前拦截形状不对的内容,减少无效请求
- 数据清洗:从混杂文本中挑出候选地址,再交给地址库规范化
- 规则匹配:在防火墙或网关的配置生成前判断字段是否形如地址
校验写法与二次确认
校验写法与二次确认
# 完整四段校验:前三个分支处理 200 以上、159 这类高位,最后一个兜底 0 到 199
^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$
# 用非捕获组写段,避免产生多余分组影响取值
import ipaddress
ip = ipaddress.ip_address(addr) # 交给地址库做权威判断
if ip.is_private or ip.is_loopback: ... # 语义判断放在库这一层
# 注意前导零:形如 010.1.1.1 的写法在部分系统会被按八进制解释
int('010') # 得到 10,而不是 010 的字面含义写法对照
| 写法 | 问题 | 结果 |
|---|---|---|
| \d{1,3}(\.\d{1,3}){3} | 不限制取值范围 | 会放过 256 与 999 |
| [0-9.]+ | 几乎什么都能过 | 点号数量与位置都失控 |
| 按区间逐段表达 | 正确表达 0 到 255 | 形状校验准确 |
| 加锚定后再匹配 | 防止部分匹配 | 1.2.3.4.5 会被拒绝 |
前导零问题不属于正则范围:010.1.1.1 在形状上可能被放行,但部分语言与系统会把带前导零的数字按八进制解释,造成校验通过而使用时含义不同,建议在规范里直接禁止前导零。
地址是否可用要按用途判断:0.0.0.0 表示不确定地址、以 127 开头的是环回、以 169.254 开头的是链路本地、255.255.255.255 是受限广播,这些都能通过形状校验但不是可分配给主机的地址。