How do I check whether a value in a string is an IP address

24,958

Solution 1

Why not let a library validate it for you? You shouldn't introduce complex regular expressions that are impossible to maintain.

% gem install ipaddress

Then, in your application

require "ipaddress"

IPAddress.valid? "192.128.0.12"
#=> true

IPAddress.valid? "192.128.0.260"
#=> false

# Validate IPv6 addresses without additional work.
IPAddress.valid? "ff02::1"
#=> true

IPAddress.valid? "ff02::ff::1"
#=> false


IPAddress.valid_ipv4? "192.128.0.12"
#=> true

IPAddress.valid_ipv6? "192.128.0.12"
#=> false

You can also use Ruby's built-in IPAddr class, but it doesn't lend itself very well for validation.

Of course, if the IP address is supplied to you by the application server or framework, there is no reason to validate at all. Simply use the information that is given to you, and handle any exceptions gracefully.

Solution 2

Ruby has already the needed Regex in the standard library. Checkout resolv.

require "resolv"

"192.168.1.1"   =~ Resolv::IPv4::Regex ? true : false #=> true
"192.168.1.500" =~ Resolv::IPv4::Regex ? true : false #=> false

"ff02::1"    =~ Resolv::IPv6::Regex ? true : false #=> true
"ff02::1::1" =~ Resolv::IPv6::Regex ? true : false #=> false

If you like it the short way ...

require "resolv"

!!("192.168.1.1"   =~ Resolv::IPv4::Regex) #=> true
!!("192.168.1.500" =~ Resolv::IPv4::Regex) #=> false

!!("ff02::1"    =~ Resolv::IPv6::Regex) #=> true
!!("ff02::1::1" =~ Resolv::IPv6::Regex) #=> false

Have fun!

Update (2018-10-08):

From the comments below i love the very short version:

!!(ip_string =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex]))

Very elegant with rails (also an answer from below):

validates :ip,
          :format => {
            :with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex)
          }

Solution 3

require 'ipaddr'
!(IPAddr.new(str) rescue nil).nil?

I use it for quick check because it uses built in library. Supports both ipv4 and ipv6. It is not very strict though, it says '999.999.999.999' is valid, for example. See the winning answer if you need more precision.

Solution 4

As most of the answers don't speak about IPV6 validation, I had the similar problem. I solved it by using the Ruby Regex Library, as @wingfire mentionned it.

But I also used the Regexp Library to use it's union method as explained here

I so have this code for a validation :

validates :ip, :format => { 
                  :with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex)
                }

Hope this can help someone !

Solution 5

Use http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ipaddr/rdoc/IPAddr.html it performs validation for you. Just rescue the exception with false and you know that it was invalid.

1.9.3p194 :002 > IPAddr.new('1.2.3.4')
 => #<IPAddr: IPv4:1.2.3.4/255.255.255.255> 
1.9.3p194 :003 > IPAddr.new('1.2.3.a')
ArgumentError: invalid address
  from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/ipaddr.rb:496:in `rescue in initialize'
  from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/ipaddr.rb:493:in `initialize'
  from (irb):3:in `new'
  from (irb):3
  from /usr/local/rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
Share:
24,958
Rohit
Author by

Rohit

https://www.rohithere.com/about/

Updated on October 09, 2020

Comments

  • Rohit
    Rohit over 3 years

    when I do this

    ip = request.env["REMOTE_ADDR"]
    

    I get the client's IP address it it. But what if I want to validate whether the value in the variable is really an IP? How do I do that?

    Please help. Thanks in advance. And sorry if this question is repeated, I didn't take the effort of finding it...

    EDIT

    What about IPv6 IP's??