将数组列表转换为ip范围

时间:2014-06-12 01:34:34

标签: ruby

有没有人知道Ruby中的一种方式,甚至是通过Web服务,如果有一个工具会在一个文件中占用一堆ip地址(目前大约有200万个)并将它们转换为ip范围,如192.168 .0.1 - 192.168.0.10?

1 个答案:

答案 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