Какой лучший (наиболее эффективный) способ анализа файла с разделителями табуляции в Ruby?
Какой лучший способ проанализировать файл с разделителями табуляции в Ruby?
Ответ 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.
-
Файлы TSV, которые на самом деле являются файлами CSV с разделителем, установленным на Tab. Это то, что вы получите, когда, например, сохраните электронную таблицу Excel как "UTF -1 6 Unicode Text". Такие файлы используют правила цитирования CSV, что означает, что поля могут содержать вкладки и символы новой строки, если они заключены в кавычки, а литеральные двойные кавычки пишутся дважды. Самый простой способ разобрать все правильно - использовать гем
csv
:use 'csv' parsed = CSV.read("file.tsv", col_sep: "\t")
-
Файлы 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)