73

Rubyでタブ区切りファイルを解析するための最良の(最も効率的な)方法は何ですか?

4

4 に答える 4

117

Ruby CSVライブラリでは、フィールド区切り文字を指定できます。Ruby1.9はFasterCSVを使用します。このようなものが機能します:

require "csv"
parsed_file = CSV.read("path-to-file.csv", col_sep: "\t")
于 2010-12-10T01:22:12.690 に答える
33

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を参照してください。

于 2013-04-25T15:57:15.817 に答える
6

実際には2種類のTSVファイルがあります。

  1. 区切り文字がTabに設定された実際のCSVファイルであるTSVファイル。これは、たとえばExcelスプレッドシートを「UTF-16Unicodeテキスト」として保存した場合に得られるものです。このようなファイルはCSV引用符ルールを使用します。つまり、引用符で囲まれている限り、フィールドにタブと改行を含めることができ、リテラルの二重引用符は2回書き込まれます。すべてを正しく解析する最も簡単な方法は、csvgemを使用することです。

    use 'csv'
    parsed = CSV.read("file.tsv", col_sep: "\t")
    
  2. IANA標準に準拠したTSVファイル。タブと改行はフィールド値として許可されておらず、引用符もありません。これは、たとえばExcelスプレッドシート全体を選択してテキストファイルに貼り付けると得られるものです(一部のセルにタブや改行が含まれていると混乱することに注意してください)。このようなTSVファイルは、簡単な方法で行ごとに簡単に解析できますline.rstrip.split("\t", -1)(注-1split空の末尾のフィールドを削除できないようにします)。csvgemを使用する場合は、次のように設定quote_charnilます。

    use 'csv'
    parsed = CSV.read("file.tsv", col_sep: "\t", quote_char: nil)
    
于 2019-07-18T08:23:09.793 に答える
0

私はmmmriesの答えが好きです。しかし、私はルビーがスプリットの終わりから空の値を取り除く方法が嫌いです。また、行末の改行も削除されません。

また、フィールド内に潜在的な改行を含むファイルがありました。そこで、彼の「解析」を次のように書き直しました。

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

これにより、必要に応じてすべての行が連結され、データの完全な行が取得され、常にデータの完全なセットが返されます(最後に潜在的なnilエントリはありません)。

于 2018-01-31T17:15:22.837 に答える