如何检查字符串中的值是否为IP地址

当我这样做的时候

ip = request.env["REMOTE_ADDR"] 

我得到了客户端的IP地址。 但是如果我想validation变量中的值是否真的是IP呢? 我怎么做?

请帮忙。 提前致谢。 抱歉,如果重复这个问题,我没有努力找到它……

编辑

那么IPv6 IP呢?

为什么不让图书馆为您validation呢? 您不应该引入无法维护的复杂正则表达式。

 % gem install ipaddress 

然后,在您的应用程序中

 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 

您也可以使用Ruby的内置IPAddr类,但它不适合validation。

当然,如果应用程序服务器或框架为您提供了IP地址,则根本没有理由进行validation。 只需使用提供给您的信息,并优雅地处理任何exception。

Ruby已经在标准库中使用了所需的Regex。 结帐解析 。

 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 

如果你喜欢它的短途…

 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 

玩得开心!

更新(2018-10-08):

从下面的评论我喜欢非常短的版本:

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

铁轨非常优雅(也是下面的答案):

 validates :ip, :format => { :with => Regexp.union(Resolv::IPv4::Regex, Resolv::IPv6::Regex) } 
 require 'ipaddr' !(IPAddr.new(str) rescue nil).nil? 

我用它来快速检查,因为它使用内置库。 支持ipv4和ipv6。 它不是很严格,例如,它说“999.999.999.999”是有效的。 如果您需要更高精度,请查看获奖答案。

由于大多数答案都不涉及IPV6validation,我遇到了类似的问题。 我使用Ruby Regex库解决了它,就像@wingfire提到的那样。

但我也使用了Regexp库来使用它的union方法,如下所述

我有这个代码进行validation:

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

希望这可以帮助别人!

以上所有答案都假设为IPv4 …您必须问自己,在迁移到IPv6的这一天,通过添加这些检查将应用程序限制为IPv4是多么明智。

如果你问我:根本不要validation它。 相反,只需将字符串按原样传递给将使用IP地址的网络组件,然后让它们进行validation。 捕获它们在出错时将抛出的exception,并使用该信息告诉用户发生了什么。 不要重新发明轮子,建立在他人的工作基础之上。

使用http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ipaddr/rdoc/IPAddr.html它会为您执行validation。 只是用false来拯救exception并且你知道它是无效的。

 1.9.3p194 :002 > IPAddr.new('1.2.3.4') => # 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 `
'
 require 'ipaddr' def is_ip?(ip) !!IPAddr.new(ip) rescue false end is_ip?("192.168.0.1") => true is_ip?("www.google.com") => false 

或者,如果您不介意扩展核心类:

 require 'ipaddr' class String def is_ip? !!IPAddr.new(self) rescue false end end "192.168.0.1".is_ip? => true "192.168.0.512".is_ip? => false 

试试这个

使用IPAddr

 require 'ipaddr' true if IPAddr.new(ip) rescue false 

我使用的这个正则表达式,我在这里找到

/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

字符串forms的IP地址必须包含四个数字,以点分隔。 每个数字必须介于0到255之间(包括0和255)。

使用正则表达式validation:

 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} 

匹配使用正则表达式的有效IP地址

 ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$ 

代替

 ^([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\.([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])){3}$ 

因为许多正则表达式引擎匹配OR序列中的第一种可能性

你可以试试你的正则表达式引擎:10.48.0.200

在这里测试差异