コード日進月歩

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

RubyのCSVクラスでheaders:trueにするとき、空白文字列の扱いに気をつける

要因がわかれば自明だけどわかりづらい、自分の引いたバッドノウハウのメモ。

環境

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

どういうことか

headerの文字列一致は空白も含めて行われる、そしてheaderの文字列が存在しないときにエラーなどは発生しないので気をつける。

下記のようなcsvがあるとする

$ cat test.csv
id,name ,age
1,taro,20
2,ziro,19
3,saburo,17

このcsvと同じディレクトリで以下のコードを sample1.rb として作る

require "csv"
CSV.foreach("test.csv",headers: true){ |row| p row["age"] }

結果としては以下

$ ruby sample1.rb
"20"
"19"
"17"

そして以下のコードを sample2.rb として作る

require "csv"
CSV.foreach("test.csv",headers: true){ |row| p row["name"] }

結果は以下のようになる

ruby sample2.rb
nil
nil
nil

このように完全に一致するヘッダがない場合はnilを返却する。正しくは以下のようなコード

require "csv"
CSV.foreach("test.csv",headers: true){ |row| p row["name "] }
ruby sample3.rb
"taro"
"ziro"
"saburo"

今回csvの列の2列目に含まれているため自明だが、末尾の列のheaderに空白が入っていると目視判断はつきづらい。例えば下記は age ではなく age だがエディタの助けがない限り判断はつかない

$ cat test.csv
id,name,age 
1,taro,20
2,ziro,19
3,saburo,17

まとめ

  • headerの行に関しては CSV.parse_line の挙動に従いパースされるので、添字に文字列を使う場合は空白文字列も含めて認識される
  • csv(さらにはtsv)の場合、末尾の空白は目視がしにくいので気をつける

関連リンク