从同时包含IPv4和IPv6的Ruby字符串中获取IPv4?

时间:2018-09-12 01:58:02

标签: ruby string ip ip-address

我有一个来自X-Forwarded-For标头的字符串,其中包含IPv4和IPv6地址。

我只需要从字符串中提取IPv4地址。

它用逗号分隔,但是它们的顺序改变了,所以我不能只拆分并拉出第二个项目。

示例:header = 2600:1740:8540:cff9:1c50:617:c9c5:63f7, 165.154.107.112

我最终只想要165.154.107.112

我正在使用Ruby 2.5.1 (这恰好是在Rails 5.2.0应用程序内部,因为它的价值)

2 个答案:

答案 0 :(得分:0)

header = "2600:1740:8540:cff9:1c50:617:c9c5:63f7, 165.154.107.112, 166.155.108.113"

header.split(/\s?,\s?/).find { |s| IPAddr.new(s).ipv4? }
  #=> "165.154.107.112"

header.split(/,\s+/).select { |s| IPAddr.new(s).ipv4? }
  #=> ["165.154.107.112", "166.155.108.113"]

请参见IPAddr::newIPAddr#ipv4?

如果"header = "是字符串str的一部分,请将header.split替换为str[/\d.+/].split

如果字符串中可能包含不是有效IP地址的文本,则可以编写以下内容。

header.split(/\s?,\s?/).find { |s| (IPAddr.new(s) rescue nil)&.ipv4? }
例如,

IPAddr.new('cat')引发异常IPAddr::InvalidAddressError (invalid address)&是Ruby的safe navigation operator,它在v2.3中首次亮相。

答案 1 :(得分:0)

假设标题始终与您发布的内容相同:

require 'ipaddr'

header = "165.154.107.112, 2600:1740:8540:cff9:1c50:617:c9c5:63f7"

ip = header.split(', ').select {|ip| ip if IPAddr.new(ip).ipv4? }.pop

# => "165.154.107.112"