IPリストを最小CIDR表現に変換

IPリストを最小CIDR表現に変換

次のIPアドレスのリストがあります。

10.10.0.0
10.10.0.1
10.10.0.2
...
10.10.0.255
172.171.0.5
...
172.171.0.67

これらのリストを取得し、そのIPアドレスの最小CIDR表現を計算するためのツールはありますか?

たとえば、上記の例では、次のような出力を取得したいと思います。

10.10.0.0/24
172.171.0.5/32
172.171.0.6/31
172.171.0.8/29
172.171.0.16/28
172.171.0.32/27
172.171.0.64/30

編集:明確にするために、「最小CIDR表現」は、私の入力ファイルのすべてのIPアドレスを含む最小のCIDR IPアドレスのセットです。

答え1

組み込みPythonモジュールの使用IPアドレス@ABが提案しましたコメントこれを提案する郵便はがき

誰でもアドレス範囲の要約(開始と終了がある)または住所を折る(リスト含む)を使用できます。

この場合、後者はより便利です。

import sys
import ipaddress

data = open(sys.argv[1],'r').read().splitlines()
ips = [ipaddress.IPv4Address(line) for line in data]
print('\n'.join([ip.with_prefixlen for ip in ipaddress.collapse_addresses(ips)]))

使用法および出力:

$ python3 cidr.py file
10.10.0.0/24
172.171.0.5/32
172.171.0.6/31
172.171.0.8/29
172.171.0.16/28
172.171.0.32/27
172.171.0.64/30

答え2

これは実際に私がしばらく解決したい問題です。このipaddressモジュールを使用して解決できますが、私の実装はおそらく不必要に複雑になるかもしれませんが、うまくいきます。

from ipaddress import IPv4Address, IPv6Address, IPv4Network, IPv6Network
addrs = ["10.10.0.0", "10.10.0.1", "10.10.0.2", "10.10.0.255", "172.171.0.5", "172.171.0.67"]
out = []
while True:
    if len(addrs) == 0:
        break
    found = False
    for index in out:
        if IPv4Network(addrs[0], 32).subnet_of(index.supernet(new_prefix=8)):
            cur = index
            while True:
                if cur.supernet_of(IPv4Network(addrs[0], 32)):
                    break
                else:
                    cur = cur.supernet()
            out[out.index(index)] = cur
            addrs.pop(0)
            found = True
            break
    if not found:
        out.append(IPv4Network(addrs.pop(0), 32).supernet())

これにより、次のような結果が表示されます。

In [81]: out
Out[81]: [IPv4Network('10.10.0.0/24'), IPv4Network('172.171.0.0/25')]

私の実装について100%確信することはできませんが、これはより良いことができると思います/8。それにしてください。

関連情報