Каков наилучший способ анализа файла с разделителями табуляции в Ruby? - PullRequest
62 голосов
/ 10 декабря 2010

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

Ответы [ 3 ]

106 голосов
/ 10 декабря 2010

Библиотека Ruby CSV позволяет указать разделитель полей.Ruby 1.9 использует FasterCSV .Примерно так будет работать:

require "csv"
parsed_file = CSV.read("path-to-file.csv", { :col_sep => "\t" })
30 голосов
/ 25 апреля 2013

Правила для 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

0 голосов
/ 31 января 2018

Мне нравится МММРИС ответ. ОДНАКО, я ненавижу то, как рубин удаляет все пустые значения из конца разделения. Он также не удаляет символ новой строки в конце строк.

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

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

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

...