🐈

\を含む文字列をvalueに持つJSONをshで標準出力する時は注意が必要という話

2022/05/14に公開

shが他のshellに対して完全に下位互換性であると考えていると怖いよという話。

$ sh -c 'echo "{ \"test\": \"a\nb\"}" > test.txt'
$ cat test.txt
=> { "test": "a
b"}
$ bash -c 'echo "{ \"test\": \"a\nb\"}" > test.txt'
$ cat test.txt
=> { "test": "a\nb"}

shのechoは出力対象になった文字列の中に制御文字と解釈してしまう。
稀なケースでCIなどにcredentialなどの情報をJSONでCIに渡したい時など変数に入れたJSONをファイルに吐き出す時にこの違いに気をつけていないと思わぬところで消耗するので注意しましょうというお話でした。

ちなみにcatの場合はshでもbashでも改行コードは単なる文字列として扱ってくれるようです。

CI環境でJSONを扱う必要が生じた場合などではbashを利用するか、echoで出力を引き渡すことは避けるようにしたほうが良いと思います。

また、エスケープされていないjson文字列を変数に入れる場合は注意が必要。
出力した文字列を変数に格納する際はsingle quateで囲まない場合はエスケープ制御によって"がサニタイズされる。

$ bash -c 'echo { "test": "a\nb"} > test.txt'
$ cat test.txt
=> { test: a\nb}
$ bash -c "echo '{ \"test\": \"a\nb\"}'" > test.txt'
$ cat test.txt
=> { "test": "a\nb"}

Discussion