Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

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

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

Ответ 4

На самом деле есть два разных типа файлов TSV.

  1. Файлы TSV, которые на самом деле являются файлами CSV с разделителем, установленным на Tab. Это то, что вы получите, когда, например, сохраните электронную таблицу Excel как "UTF -1 6 Unicode Text". Такие файлы используют правила цитирования CSV, что означает, что поля могут содержать вкладки и символы новой строки, если они заключены в кавычки, а литеральные двойные кавычки пишутся дважды. Самый простой способ разобрать все правильно - использовать гем csv:

    use 'csv'
    parsed = CSV.read("file.tsv", col_sep: "\t")
    
  2. Файлы TSV, соответствующие стандарту IANA. Вкладки и переводы строк не допускаются в качестве значений полей, и никаких кавычек нет. Это то, что вы получите, когда, например, выберете целую электронную таблицу Excel и вставите ее в текстовый файл (будьте осторожны: это может испортиться, если некоторые ячейки содержат вкладки или переводы строк). Такие файлы TSV можно легко анализировать построчно с помощью простого line.split("\t", -1) (обратите внимание -1, который не позволяет split удалять пустые конечные поля). Если вы хотите использовать гем csv, просто установите quote_char в nil:

    use 'csv'
    parsed = CSV.read("file.tsv", col_sep: "\t", quote_char: nil)