コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

RubyのCSVクラスを使ってTSVを読み込む場合にダブルコーテーションの入っているものがあるときの対策

パースエラーになる、のでワークアラウンド的な対策

環境

$ ruby -v
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin19]

やりたいこと

正常に変換できるケース

例えば以下のような test1.tsv があるとする(タブはHTMLの表現上うまく出ないので雰囲気だけ)

id    name    text
1   taro    sample text
2   ziro    hello!
3   saburo  cry

この場合に以下のようにすれば読み取れる

require "csv"
result1 = CSV.read("test1.tsv", col_sep: "\t", headers: true)
result1[1]["text"]
# => "hello!"

異常がおきるケース

例えば以下のような test2.tsv の場合は、ダブルコーテーションが入っている要素があるのでパースできない。

id    name    text
1   taro    sample text
2   ziro    say "hello"
3   saburo  cry

この場合、パースエラーが出てデータが取れない

require "csv"
result2 = CSV.read("test2.tsv", col_sep: "\t", headers: true)
# /Users/hogehoge/.anyenv/envs/rbenv/versions/3.0.1/lib/ruby/3.0.0/csv/parser.rb:925:in `parse_quotable_robust': Illegal quoting in line 3. (CSV::MalformedCSVError)

回避策

エラーとしてはもともとのCSVとしての仕様として " で各要素を囲むことに対する仕様があるため、そちらとの兼ね合いで正確にパースができず失敗してしまう。

そのため、この厳密さを回避するオプションである liberal_parsing: true とパース自体はすることができる。

result2_ex = CSV.read("test2.tsv", col_sep: "\t", headers: true,liberal_parsing: true )
result2_ex[1]["text"]
# => "say \"hello\""

関連リンク