Ruby で to_yaml するときは、改行コードを LF で統一する。
Ruby 付属の YAML モジュールは、下のような動作をする。文字列を直接 to_yaml した時だけでなく、配列やハッシュの値だった場合も同じ。
- "\r"をto_yamlしてloadするとnilになる。
- "010\r"をto_yamlしてloadすると8になる。
- "010\n"をto_yamlしてloadすると"010\n"になる。OK。
- "false\r"をto_yamlしてloadするとfalseになる。
- "false\n"をto_yamlしてloadすると"false\n"になる。OK。
- "\n\n\n\n"をto_yamlしてloadすると空文字列になる。
- "1\r\n\r\n\r\n"をto_yamlしてloadすると"1\n"になる。
to_yaml実用にならない気がしてきた。次善の策として to_yaml の前に \r\n と \r を \n に統一、\nだけの文字列は空白に変換して乗り切る。
(追記) ya2yamlを入れたらだいぶ改善した。まだ変だけど。
$ sudo gem install ya2yaml require 'rubygems' require 'ya2yaml' $KCODE = 'u' p "\r".ya2yaml
実験
の実行結果。
--- \rはnilになる。 "\r" nil "\n" --- 複数の\rは1個減る。 "\r\r\r" "\r\r" "" --- \nは空文字列になる。 "\n" "" "\n" --- 複数の\nも空文字列になる。 "\n\n\n" "" "" --- \r\nは空文字列になる。 "\r\n" "" "" --- 複数の\r\nも空文字列になる。 "\r\n\r\n\r\n" "" "" --- 配列でも同じ。\rはnilの要素が含まれてしまう!エラーの可能性。 ["1", "\r", "2"] ["1", nil, "2"] ["1", "\n", "2"] --- 複数の\rを含む配列。 ["1", "\r\r\r", "2"] ["1", "\r\r", "2"] ["1", "", "2"] --- ハッシュも同じ。 {:a=>"1", :x=>"\r", :b=>"2"} {:a=>"1", :x=>nil, :b=>"2"} {:a=>"1", :x=>"\n", :b=>"2"} --- \nや\r\nも同じ。空文字列が配列の要素になる。 ["1", "\n\n\n\n", "2"] ["1", "", "2"] ["1", "", "2"] --- 通常は、文字列の数字をちゃんと扱える。 "1" "1" "1" --- \rが付くと数値になる。なにそれ! "1\r" 1 "1\n" --- "010\r"は8になってしまう。8進数。 "010\r" 8 "010\n" --- 同様に16進数。 "0x10\r" 16 "0x10\n" --- 同様にfloat。 "0.2\r" 0.2 "0.2\n" --- boolean。nilか文字列かみたいな判定をしてると失敗する。 ["a", "false\r", "b"] ["a", false, "b"] ["a", "false\n", "b"] --- \nは大丈夫。数字 "1\n" "1\n" "1\n" --- \nは大丈夫。boolean "true\n" "true\n" "true\n" --- 文字列に\rが複数付いたら一個減る。まだマシ。 "1\r\r" "1\r" "1\n\n" --- 先頭が#だと\rは消えない。 "# a\r" "# a\r" "# a\n" --- 文字列の中では正しく扱える。\rの場合 "1\r2" "1\r2" "1\n2" --- 文字列の中では正しく扱える。複数の\rもOK。 "1\r\r2" "1\r\r2" "1\n\n2" --- 文字列中の\rは正しく扱えるが、末尾の\rは消える。 "1\r\r2\r" "1\r\r2" "1\n\n2\n" --- 末尾の\nは正しく扱える。 "1\n" "1\n" "1\n" --- 末尾の\nは正しく扱える。 "1\n\n" "1\n\n" "1\n\n" --- 文字列中の\nは正しく扱える。 "1\n\n2\n" "1\n\n2\n" "1\n\n2\n" --- \r\nは\nになる。 "1\r\n" "1\n" "1\n" --- \r\nの繰り返しは1つの\nになる。 "1\r\n\r\n\r\n" "1\n" "1\n\n\n"