Ruby:如何将IP范围转换为IP数组

4
有没有简单的方法将IP范围转换为IP数组?
def convertIPrange (start_ip, end_ip)
 #output: array of ips end
end

例如输入
('192.168.1.105', '192.168.1.108') 

输出

['192.168.1.105','192.158.1.106','192.158.1.107','192.158.1.108']

虽然将范围转换为数组很容易,但这样做时要非常小心。范围是一种非常紧凑和高效的存储端点的方式,因为它仅仅是端点。另一方面,数组包含所有点,包括其中的所有点,这些点都会占用内存。考虑包含/8 CIDR中IP的数组的影响。如果涉及更大的网络或IPv6,则情况只会变得更糟。 - the Tin Man
2个回答

10

使用Ruby标准库IPAddr

# I would suggest naming your function using underscore rather than camelcase
# because of Ruby naming conventions
#
require 'ipaddr'

def convert_ip_range(start_ip, end_ip)
  start_ip = IPAddr.new(start_ip)
  end_ip   = IPAddr.new(end_ip)

  # map to_s if you like, you can also call to_a, 
  # IPAddrs have some neat functions regarding IPs, 
  # be sure to check them out
  #
  (start_ip..end_ip).map(&:to_s) 
end

只有使用IPAddr的答案才能得到+1。IPAddress gem在进行网络操作时功能更加全面。 - the Tin Man
+1,但是IPAddr不在核心中,而是在标准库中。 - steenslag
这个答案正确的原因是,IPAddr将自动处理不仅是最后一个八位组改变的IP范围。这将导致一个大数组,但它仍然会做正确的事情。 - the Tin Man
@theTinMan 我的回答也是这样。 - sawa
@steenslag 谢谢,我把它们搞混了。已经更正了。 - Beat Richartz
谢谢! - Francois

2
def convertIPrange first, last
  first, last = [first, last]
    .map{|s| s.split(".").inject(0){|i, s| i = 256 * i + s.to_i}}
  (first..last).map do |q|
    a = []
    (q, r = q.divmod(256)) && a.unshift(r) until q.zero?
    a.join(".")
  end
end

convertIPrange('192.168.1.105', '192.168.1.108')
# => ["192.168.1.105", "192.168.1.106", "192.168.1.107", "192.168.1.108"]

convertIPrange('192.255.255.254', '193.0.0.1')
# => ["192.255.255.254", "192.255.255.255", "193.0.0.0", "193.0.0.1"]

s/convertIPrange/convert_ip_range/ - the Tin Man
@theTinMan 我不喜欢这个方法的名字,但这就是问题提出者所问的。如果我使用不同的名称编写一个方法,那就无法回答问题提出者的问题。 - sawa
@theTinMan,你说另一个答案是唯一做正确事情的答案。那这个有什么问题吗? - sawa
虽然这段代码可以工作,但它没有利用内置的Class,该Class提供了许多其他功能,包括检查提交的IP地址是否有效。请尝试使用puts convertIPrange('0.0.0.0', '0.0.0.256') - the Tin Man
@theTinMan OP没有提到它可能来自用户输入,所以我假设这些值是有效的。虽然我不知道这个库,但同意使用它更好。 - sawa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接