2016-12-29 91 views
1

在Ruby中,我該如何解析CSV文件並輸出相應的信息?例如:解析特定IP地址的CSV文件

require 'csv' 

class CountryFilter 

    class << self 

    def find_specs_by_ip_address(ip) 
     CSV.foreach('GeoIPCountry.csv') do |row| 
     if row =~ Regexp.union(ip) 
      data = row.split(',') 
      return data[5] 
     else 
      return 'Unable to find country specifications' 
     end 
     end 
    end 

    end 

end 

puts CountryFilter.find_specs_by_ip_address('72.247.167.255') 

CSV文件:

... 
"72.247.88.0","72.247.89.255","1224169472","1224169983","US","United States" 
"72.247.90.0","72.247.103.255","1224169984","1224173567","NL","Netherlands" 
"72.247.104.0","72.247.144.255","1224173568","1224184063","US","United States" 
"72.247.145.0","72.247.145.255","1224184064","1224184319","NL","Netherlands" 
"72.247.146.0","72.247.167.255","1224184320","1224189951","US","United States" 
"72.247.168.0","72.247.179.255","1224189952","1224193023","NL","Netherlands" 
"72.247.180.0","72.247.181.255","1224193024","1224193535","US","United States" 
"72.247.182.0","72.247.182.255","1224193536","1224193791","NL","Netherlands" 
"72.247.183.0","72.247.183.255","1224193792","1224194047","US","United States" 
... 

如何可以解析爲IP地址,並輸出其來源國這個CSV文件?

+1

我想前兩列實際上表示IP範圍。 – Felix

回答

1

  • row已經是一個CSV行與多個單元格,你不必拆東西和定義data
  • 在這兩種情況下,您的方法在第一行後返回:IP找到與否。
  • 當找不到IP時返回nil可能比返回字符串更好。

重構的代碼

require 'csv' 
class CountryFilter 
    class << self 
    def find_specs_by_ip_address(ip) 
     CSV.foreach('GeoIPCountry.csv') do |row| 
     return row.last if row.first(2).include?(ip) 
     end 
    end 
    end 
end 

CountryFilter.find_specs_by_ip_address('72.247.167.255') 
#=> "United States 
CountryFilter.find_specs_by_ip_address('1.2.3.4') 
#=> nil 

V2

感謝@Felix了有見地的意見。

此方法現在認爲IP1和IP2是一個IP範圍的邊界,並且檢查是否ip在該範圍內:

require 'csv' 
require 'ipaddr' 

module IPFilter 
    def self.find_country_by_ip_address(ip) 
    ip = IPAddr.new(ip).to_i 
    CSV.foreach('GeoIPCountry.csv') do |_, _, ip1, ip2, _, country_name| 
     return country_name if (ip1.to_i..ip2.to_i).cover?(ip) 
    end 
    end 
end 

p IPFilter.find_country_by_ip_address('72.247.167.123') 
#=> "United States" 
p IPFilter.find_country_by_ip_address('1.2.3.4') 
#=> nil 

Range#cover?

返回true如果obj之間範圍的開始和結束。

+0

awh,解釋它!非常感謝 – User9123

+0

會不會有一種方法可以找到接近IP的匹配結果爲零?例如讓我說我有127.0.0.1,如果它沒有找到最接近的匹配127.0.0.1等。 – User9123

+1

請寫另一個問題,因爲結構會不同於當前的一個 –

0

試試這個,

... 
CSV.foreach('GeoIPCountry.csv') do |a, b, c, d, e, country| 
    return country if a == ip || b == ip 
end 
... 

這是如何工作的?

  • row已經由逗號
  • 拆分可以解開行中的塊參數,以避免幻數

NB,最好給a, b, c, d, e更有意義的名稱。