Dani El
Dani El

Reputation: 439

Cleaner way to increment last IPv4 digit

Here is my IP: 192.168.2.0

I need to get an array like this one:

["192.168.2.0",
 "192.168.2.1",
 "192.168.2.2",
 "192.168.2.3",
 "192.168.2.4",
 "192.168.2.5"]

Here is how i increment last digit up to 5:

ip = '192.168.2.0'

ips = 0.upto(5).map do |n|
  ip.sub(/\.\d+$/, '.' << n.to_s)
end

However it is dog slow and i hate how it looks.

Important - i need initial ip to stay untouched so i can later refer to it via ip variable.

Upvotes: 0

Views: 1262

Answers (4)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230521

Try this one, it uses split/join instead of regexes.

ip = '192.168.2.0'

ips = 0.upto(5).map do |n|
  ip.split('.').tap{|i| i[-1] = n }.join('.')
end

Upvotes: 1

steenslag
steenslag

Reputation: 80085

The Standard lib has IPAddr, which supports a succ method.

require 'ipaddr'
ip = "192.168.2.0"

ips = [ip]
5.times do 
  ips << IPAddr.new(ips.last).succ.to_s
end
p ips
# =>["192.168.2.0", "192.168.2.1", "192.168.2.2", "192.168.2.3", "192.168.2.4", "192.168.2.5"]

#Ranges work:
ip_range = IPAddr.new("192.168.2.0")..IPAddr.new("192.168.2.5")
p ip_range.map(&:to_s)
# =>["192.168.2.0", "192.168.2.1", "192.168.2.2", "192.168.2.3", "192.168.2.4", "192.168.2.5"]

Upvotes: 4

codatory
codatory

Reputation: 686

I would recommend using IPAddr from stdlib as it will gracefully handle the octet rollover (when you hit .255) and also has some useful features for subnetting and such.

require 'ipaddr'
current = ip = IPAddr.new('192.168.2.0')
array = [ip]
until current.to_s == '192.168.2.5'
  array << current = current.succ
end
array.map!(&:to_s)

Upvotes: 1

user904990
user904990

Reputation:

As long as you deal with digits under 9 you can use succ(or next):

ip = '192.168.2.0'

p (0...5).inject([ip]) { |l| l << l.last.succ }

#=> ["192.168.2.0", "192.168.2.1", "192.168.2.2", "192.168.2.3", "192.168.2.4", "192.168.2.5"]

If you'll need to increment to say up to 255, use split which is much faster than regex:

p (0..255).inject([ip]) { |l, d| l << (l.last.split('.')[0..2] << d).join('.') }

#=> ["192.168.2.0" ... "192.168.2.255"]

See live demo here

Upvotes: 1

Related Questions