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

実験

の実行結果。

  • 1行目 コメント
  • 2行目 入力
  • 3行目 YAML.load(入力.to_yaml) の結果
  • 4行目 YAML.load(入力.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"