調べたら有名な話らしいが, 一応備忘録として書いておく.
参考: https://stackoverflow.com/questions/36277870/zsh-why-is-n-interpreted-within-single-quotes
問題
最近 Bash から Zsh に乗り換えたのだが, 以下の様な動作の違いに遭遇し困惑した.
echo 'hoge\nfuga'
を Bash と Zsh でそれぞれ実行すると
$ echo 'hoge\nfuga'
hoge\nfuga
$ echo 'hoge\nfuga'
hoge
fuga
となり, \n
が改行文字として解釈されるか否かが異なる.
echo
コマンドはオプション -e
をつけない限り \n
の様なエスケープシーケンスは解釈せずそのまま出力するものと理解していたため, Zsh は echo
に渡す前に \n
を改行文字に置き換えるのか? (シングルクオーテーションで囲っているのに?) などと混乱した.
解決
原因は echo
の方にあった. type
でそれぞれが呼んでいる echo
が何なのかを調べると,
$ type echo
echo is a shell builtin
$ type echo
echo is a shell builtin
両者ともビルトインの echo
を呼んでいる. しかしそれぞれのビルトインの仕様に差があるようだ.
マニュアル(Bash, Zsh)を読んでみると, (あまり明示的には書かれていないが文脈から考えると) Bash の方はデフォルトではエスケープシーケンスを解釈しない一方 Zsh は解釈するみたいだ.
Bash:
If the -e option is given, interpretation of the following backslash-escaped characters is enabled. The -E option disables the interpretation of these escape characters, even on systems where they are interpreted by default. The xpg_echo shell option may be used to dynamically determine whether or not echo expands these escape characters by default.
Zsh:
The -E flag, or the BSD_ECHO option, can be used to disable these escape sequences. In the latter case, -e flag can be used to enable them.
まとめ
echo
コマンドの可搬性には気を付けましょう.