You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:将大量零散IP/子网合并为完整子网的脚本优化问题

问题解决:IP地址与子网的批量合并优化

原脚本的核心问题

  1. 未处理输入中的子网条目:原脚本默认所有输入都是单个IP,无法解析xx2.24.7.0/23这类子网格式,会直接报错或错误处理。
  2. 仅支持/24子网合并:没有考虑/22、/23、/25等其他掩码的完整子网检测。
  3. 未去重与优先级处理:输入中可能同时存在子网和单个IP,原脚本未做去重,也没有按从大到小的子网优先级合并,导致大网段无法被正确识别。

修正方案

实现思路

  1. 统一解析输入:区分单个IP和子网,将所有条目转换为IPv4地址集合,自动去重。
  2. 按优先级检测完整子网:从大掩码(/22)到小掩码(/25)依次检查,确保大网段优先被识别,避免被拆分为小网段。
  3. 标记已处理IP:每识别一个完整子网,就将该子网内的所有IP从集合中移除,避免重复处理为单个IP。
  4. 输出剩余单个IP:未被子网覆盖的IP以/32格式输出。

修正后的代码

import ipaddress
from collections import defaultdict

def parse_input(input_lines):
    # 存储所有存在的IP,用集合去重
    existing_ips = set()
    # 存储输入中已经存在的子网(后续要优先检查这些子网是否完整)
    input_subnets = set()

    for line in input_lines:
        line = line.strip()
        if not line:
            continue
        try:
            # 尝试解析为子网
            net = ipaddress.IPv4Network(line, strict=False)
            input_subnets.add(net)
            # 将子网内的所有IP加入集合
            for ip in net.hosts():
                existing_ips.add(ip)
        except ValueError:
            # 解析失败则当作单个IP处理
            try:
                ip = ipaddress.IPv4Address(line)
                existing_ips.add(ip)
            except ValueError:
                print(f"无效条目,跳过:{line}")
                continue
    return existing_ips, input_subnets

def find_complete_subnets(existing_ips, input_subnets):
    # 定义需要检查的子网掩码,按从大到小优先级排列
    prefix_lengths = [22, 23, 24, 25]
    complete_subnets = set()
    # 复制IP集合用于修改
    remaining_ips = existing_ips.copy()

    # 先检查输入中已有的子网是否完整
    for net in input_subnets:
        if net.prefixlen not in prefix_lengths:
            continue
        # 检查子网内所有主机IP是否都存在
        all_present = True
        for ip in net.hosts():
            if ip not in remaining_ips:
                all_present = False
                break
        if all_present:
            complete_subnets.add(net)
            # 移除已处理的IP
            for ip in net.hosts():
                remaining_ips.discard(ip)

    # 再自动检测所有可能的完整子网
    for prefix in prefix_lengths:
        # 按当前掩码分组剩余IP
        ip_groups = defaultdict(set)
        for ip in remaining_ips:
            # 获取IP所属的当前掩码子网
            subnet = ipaddress.IPv4Network((ip, prefix), strict=False)
            ip_groups[subnet].add(ip)
        
        # 检查每个分组是否是完整子网
        for subnet, ips in ip_groups.items():
            # 计算该子网应有的主机数(总IP数减网络地址和广播地址)
            expected_hosts = 2 ** (32 - prefix) - 2
            if len(ips) == expected_hosts:
                complete_subnets.add(subnet)
                # 移除已处理的IP
                remaining_ips -= ips

    return complete_subnets, remaining_ips

def write_results(complete_subnets, remaining_ips, output_file):
    with open(output_file, "w") as f:
        # 先写入完整子网,按掩码从大到小排序
        sorted_subnets = sorted(complete_subnets, key=lambda x: (x.prefixlen, x.network_address))
        for subnet in sorted_subnets:
            f.write(f"{subnet}\n")
        # 写入剩余的单个IP,按地址排序
        sorted_ips = sorted(remaining_ips)
        for ip in sorted_ips:
            f.write(f"{ip}/32\n")

def main(input_file, output_file):
    with open(input_file, "r") as f:
        input_lines = f.readlines()
    
    existing_ips, input_subnets = parse_input(input_lines)
    complete_subnets, remaining_ips = find_complete_subnets(existing_ips, input_subnets)
    write_results(complete_subnets, remaining_ips, output_file)

if __name__ == "__main__":
    input_file = "input.txt"
    output_file = "output.txt"
    main(input_file, output_file)

代码说明

  1. parse_input函数:负责解析所有输入条目,将子网展开为IP集合,同时记录输入中已有的子网,自动过滤无效条目。
  2. find_complete_subnets函数:
    • 优先检查输入中已有的子网是否完整,确保用户预定义的网段优先被处理。
    • 按/22→/23→/24→/25的顺序自动检测完整子网,避免小网段先被识别导致大网段无法合并。
    • 每识别一个完整子网,立即移除对应IP,避免重复处理。
  3. write_results函数:按掩码从大到小排序输出子网,按IP地址排序输出剩余单个IP,保证结果整洁有序。

内容的提问来源于stack exchange,提问作者mcalavera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:54:51