Каков наилучший способ проанализировать файл с разделителями табуляции в Ruby?


каков наилучший (наиболее эффективный) способ анализа файла с разделителями табуляции в Ruby?

3 57

3 ответа:

библиотека CSV Ruby позволяет указать разделитель полей. Ruby 1.9 использует FasterCSV. Что-то вроде этого будет работать:

require "csv"
parsed_file = CSV.read("path-to-file.csv", { :col_sep => "\t" })

правила для TSV на самом деле немного отличаются от CSV. Основное различие заключается в том, что CSV имеет положения для вставки запятой внутри поля, а затем с помощью символов кавычек и экранирования кавычек внутри поля. Я написал быстрый пример, чтобы показать, как простой ответ терпит неудачу:

require 'csv'
line = 'boogie\ttime\tis "now"'
begin
  line = CSV.parse_line(line, col_sep: "\t")
  puts "parsed correctly"
rescue CSV::MalformedCSVError
  puts "failed to parse line"
end

begin
  line = CSV.parse_line(line, col_sep: "\t", quote_char: "Ƃ")
  puts "parsed correctly with random quote char"
rescue CSV::MalformedCSVError
  puts "failed to parse line with random quote char"
end

#Output:
# failed to parse line
# parsed correctly with random quote char

Если вы хотите использовать библиотеку CSV, вы можете использовать случайный символ цитаты, который вы не ожидаете увидеть, если ваш файл (пример показывает это), но вы также можете использовать более простой методология, такая как класс StrictTsv, показанный ниже, чтобы получить тот же эффект, не беспокоясь о котировках полей.

# The main parse method is mostly borrowed from a tweet by @JEG2
class StrictTsv
  attr_reader :filepath
  def initialize(filepath)
    @filepath = filepath
  end

  def parse
    open(filepath) do |f|
      headers = f.gets.strip.split("\t")
      f.each do |line|
        fields = Hash[headers.zip(line.split("\t"))]
        yield fields
      end
    end
  end
end

# Example Usage
tsv = Vendor::StrictTsv.new("your_file.tsv")
tsv.parse do |row|
  puts row['named field']
end

выбор использования библиотеки CSV или чего-то более строгого просто зависит от того, кто отправляет вам файл и ожидают ли они придерживаться строгого стандарта TSV.

подробности о стандарте TSV можно найти по адресу http://en.wikipedia.org/wiki/Tab-separated_values

Мне нравится ответ mmmries. Тем не менее, я ненавижу то, как ruby удаляет любые пустые значения с конца раскола. Он также не снимает новую строку в конце строк.

кроме того, у меня был файл с потенциальными строк в поле. Итак, я переписал его "разбор" следующим образом:

def parse
  open(filepath) do |f|
    headers = f.gets.strip.split("\t")
    f.each do |line|
      myline=line
      while myline.scan(/\t/).count != headers.count-1
        myline+=f.gets
      end
      fields = Hash[headers.zip(myline.chomp.split("\t",headers.count))]
      yield fields
    end
  end
end

это связывает любые строки, необходимые для получения полной строки данных, и всегда возвращает полный набор данных (без потенциальных нулевых записей в конце).