有没有人知道Ruby中的一种方式,甚至是通过Web服务,如果有一个工具会在一个文件中占用一堆ip地址(目前大约有200万个)并将它们转换为ip范围,如192.168 .0.1 - 192.168.0.10?
答案 0 :(得分:1)
将IP地址转换为32位整数(假设您根据帖子处理IPv4地址),删除重复项,对它们进行排序,然后进行合并。之后,将整数转换回IP字符串:
require 'ipaddr'
def to_ranges(ips)
ips = ips.map{|ip| IPAddr.new(ip).to_i }.uniq.sort
prev = ips[0]
ips
.slice_before {|e|
prev2, prev = prev, e
prev2 + 1 != e
}
.map {|addrs| if addrs.length > 1 then [addrs[0], addrs[-1]] else addrs end }
.map {|addrs| addrs.map{|ip| IPAddr.new(ip, Socket::AF_INET)}.join("-") }
end
# some ip samples
ips = (0..255).map{|i| ["192.168.0.#{i}", "192.168.1.#{i}", "192.168.2.#{i}"] }.reduce(:+)
ips += ["192.168.3.0", "192.168.3.1"]
ips += ["192.168.3.5", "192.168.3.6"]
ips += ["192.168.5.1"]
ips += ["192.168.6.255", "192.168.7.0", "192.168.7.1"]
p to_ranges(ips)
# => ["192.168.0.0-192.168.3.1", "192.168.3.5-192.168.3.6", "192.168.5.1", "192.168.6.255-192.168.7.1"]
从文件中读取IP地址并将其存储在数组中应该相对容易。 200万个IP地址是一个小集合。您不必担心内存使用情况。 (如果真的很重要,您可能需要实现一种算法来逐步转换和合并地址)
顺便说一下,我在解决你的问题时找到了方便的方法Enumerable#slice_before。