2010-12-10 4 views

Antwort

92

In der Ruby CSV-Bibliothek können Sie das Feldtrennzeichen angeben. Ruby 1.9 verwendet FasterCSV. So etwas würde funktionieren:

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

Beachten Sie, dass dieser Ansatz fehlschlägt, wenn einer der durch Tabulatoren getrennten Werte einen doppelten Anführungsstrich enthält. Der StrictTsv-Vorschlag in der anderen Antwort ist robuster. –

23

Die Regeln für TSV sind eigentlich ein bisschen anders als CSV. Der Hauptunterschied besteht darin, dass CSV Vorkehrungen für das Einfügen eines Kommas in ein Feld und das Verwenden von Anführungszeichen und das Entfernen von Anführungszeichen in einem Feld enthält. Ich schrieb ein kleines Beispiel zu zeigen, wie die einfache Antwort ausfällt:

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 

Wenn Sie die CSV-Bibliothek verwenden möchten, können Sie eine zufällige Anführungszeichen verwendet, die Sie nicht erwarten, wenn Sie Ihre Datei (im Beispiel zu sehen Dies kann aber auch mit einer einfacheren Methode wie der StrictTsv-Klasse erreicht werden, um den gleichen Effekt zu erzielen, ohne sich um Feldnotierungen kümmern zu müssen.

# 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 

Die Wahl der Verwendung hängt die CSV-Bibliothek oder etwas strenger nur auf die Sie die Datei sendet und ob sie erwarten den strengen TSV Standard einzuhalten.

Details zu dem TSV-Standard können bei http://en.wikipedia.org/wiki/Tab-separated_values

+0

Bitte fügen Sie Code-Snippets mit der Antwort ein, * nicht * in einem externen Text. Dieser Punkt scheint jetzt zu sein, was sehr schade ist. –

+4

@JezenThomas danke für die heads-up. Ich habe alle Code-Beispiele inline gezogen, um das Problem zu beheben, dass ich die gist – mmmries

+0

große Antwort betrachten muss. . Ich bin überrascht, wie schrecklich '\ d' mit dem CSV-Parser fehlschlägt. – dps

0

Ich mag mmmries Antwort zu finden. JEDOCH hasse ich die Art und Weise, wie Ruby irgendwelche leeren Werte vom Ende einer Spaltung entfernt. Es wird auch nicht die Zeilenschaltung am Ende der Zeilen entfernen.

Außerdem hatte ich eine Datei mit möglichen Zeilenumbrüchen in einem Feld. Also schrieb ich seine ‚Parse‘ wie folgt:

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 

Diese verkettet alle Zeilen wie nötig eine komplette Linie von Daten zu erhalten, und gibt immer den vollen Satz von Daten (ohne Potential null Einträge am Ende).

Verwandte Themen