Bash对比两个IP列表变量时如何忽略指定IP段比对差异
Shell实现逗号分隔IP段精准过滤与差异比对
需求说明
- 变量
L1存储从Cloudflare官方下载的最新逗号分隔IP段列表 - 变量
L2存储从现有YAML配置中读取的已配置逗号分隔IP段列表 - 比对前需从
L2中精准移除指定排除段1.2.3.0/32,不得误删其他IP段 - 排除指定段后若两个列表存在差异,触发邮件告警
- 已知
grep会跳过匹配整行、tr会删除所有匹配字符,无法满足单IP段精准移除要求
现有操作流程
- 下载Cloudflare官方IPv4、IPv6地址段
wget https://www.cloudflare.com/ips-v4 && wget https://www.cloudflare.com/ips-v6
- 拼接下载的IP段为逗号分隔格式,赋值给
L1
L1=$(awk '{printf fmt,$1}' fmt="%s\n" ips-v4 ips-v6 | paste -sd, -)
- 从目标YAML配置读取已配置IP段,赋值给
L2
L2=$(yq -r .controller.config.proxy-real-ip-cidr yaml.yaml)
变量实际输出示例
L1执行输出:
173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32
L2执行输出(末尾包含需排除的1.2.3.0/32):
173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32,1.2.3.0/32
具体实现方案
不要直接在整串上做字符串替换,很容易因为IP段子串匹配误删内容,最稳妥的方式是把逗号分隔的列表拆成单个IP段条目,逐段精确匹配过滤,再排序后做差集,还能避免两个列表IP段顺序不一致导致的误报。
1. 精准过滤L2中指定排除的IP段
通过指定逗号为行分隔符,逐段做精确匹配,只有完全等于排除段的条目才会被跳过,自动适配排除段在列表开头、中间、末尾的所有场景,不会误改其他IP段:
# 定义需要排除的IP段 EXCLUDE_CIDR="1.2.3.0/32" # 过滤后重新拼接为逗号分隔格式 L2_CLEAN=$(awk -v exclude="$EXCLUDE_CIDR" 'BEGIN{RS=",";ORS=","} $0!=exclude {print}' <<< "$L2" | sed 's/,$//')
2. 标准化两个列表避免顺序干扰
IP段配置不区分先后顺序,因此将两个列表拆分为单个条目后排序,再重新拼接为统一格式,避免顺序不同导致的误报:
# 处理官方最新IP段列表 L1_STD=$(tr ',' '\n' <<< "$L1" | sort | paste -sd, -) # 处理过滤后的已配置IP段列表 L2_STD=$(tr ',' '\n' <<< "$L2_CLEAN" | sort | paste -sd, -)
3. 差异判断与告警触发
直接比对标准化后的两个字符串即可判断是否存在差异,需要排查具体差异时可以用comm命令输出两边独有的段:
if [ "$L1_STD" != "$L2_STD" ]; then echo "=== 检测到Cloudflare IP段配置与官方最新列表存在差异 ===" # 输出具体差异明细 echo "官方列表存在、配置中缺失的段:" comm -23 <(tr ',' '\n' <<< "$L1_STD") <(tr ',' '\n' <<< "$L2_STD") echo "配置中存在、官方列表没有的段:" comm -13 <(tr ',' '\n' <<< "$L1_STD") <(tr ',' '\n' <<< "$L2_STD") # 此处替换为实际的邮件告警命令 # mail -s "Cloudflare IP段变更告警" admin@example.com < <(echo "IP段配置存在差异,请及时更新") fi
效果验证
针对给出的示例变量:
- 过滤后的
L2_CLEAN会精准移除末尾的1.2.3.0/32,不会改动其他段 - 比对时会准确识别出配置中
104.16.0.0/12与官方段104.16.0.0/13、104.24.0.0/14的差异,无漏报误报
内容的提问来源于stack exchange,提问作者DisplayName
相关产品推荐
相关产品推荐

