Humanity

Edit the world by your favorite way

エスケープシーケンス

シェルを再発明してたらzsh 4.2.6で

$ echo "\\\\"

とやると

\

としか表示されないことに気づいた。
あとダブルクォートかシングルクォートか裸のままかでも結果が違ったので、
それぞれzshbashで比較してみる。

環境

$ cat /etc/redhat-release
CentOS release 5.3 (Final)
$ zsh --version
zsh 4.2.6 (i686-redhat-linux-gnu)
$ bash --version
GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
$ file $(which sh)
/bin/sh: symbolic link to 'bash'

実験用スクリプト

echo
echo 'echo double quotes x 3:[' "\\\\\\" ']'
echo 'echo double quotes x 2:[' "\\\\" ']'
echo 'echo double quotes x 1:[' "\\" ']'

echo
echo 'echo single quotes x 3:[' '\\\\\\' ']'
echo 'echo single quotes x 2:[' '\\\\' ']'
echo 'echo single quotes x 1:[' '\\' ']'

echo
echo 'echo literal quotes x 3:[' \\\\\\ ']'
echo 'echo literal quotes x 2:[' \\\\ ']'
echo 'echo literal quotes x 1:[' \\ ']'

おぞましいスクリプトですね。
僕のLinux環境では「\」は円マークではなくバックスラッシュに見えるので多少はギザギザした感じはないのですが、2つ並んだバックスラッシュを見ると逃げ出したくなる病患者なのでかなり嫌な感じです。


出力結果

まずはbash

echo double quotes x 3:[ \\\ ]
echo double quotes x 2:[ \\ ]
echo double quotes x 1:[ \ ]

echo single quotes x 3:[ \\\\\\ ]
echo single quotes x 2:[ \\\\ ]
echo single quotes x 1:[ \\ ]

echo literal quotes x 3:[ \\\ ]
echo literal quotes x 2:[ \\ ]
echo literal quotes x 1:[ \ ]

まぁ合ってるだろうと思われる結果になった。


次にzsh

echo double quotes x 3:[ \\ ]
echo double quotes x 2:[ \ ]
echo double quotes x 1:[ \ ]

echo single quotes x 3:[ \\\ ]
echo single quotes x 2:[ \\ ]
echo single quotes x 1:[ \ ]

echo literal quotes x 3:[ \\ ]
echo literal quotes x 2:[ \ ]
echo literal quotes x 1:[ \ ]

うがが。全然違う。




※以下、この解釈の仕方がバグだとして話を進めます。
これがzshにおける正しい式の解釈だよ!って場合はコメント欄で教えていただけると幸いです。


まず上から2番目は気づいたきっかけとなったもの。

式:

echo 'echo double quotes x 2:[' "\\\\" ']'

結果:

echo double quotes x 2:[ \ ]

なんかこれ式のバックスラッシュのとこだけ2回評価してるような。

ダブルクォートによる評価(1回目)→全体の式の評価

みたいな?(適当


シングルクォートはひどいというよりも、むしろ「ダブルクォートだったら」正しい解釈と言える。
リテラルはダブルクォートと一緒。


あと一番アレだと思ったのは、

$ echo '\n'

zshだときっちり改行されてしまうこと。




やっぱり

zshはまだまだ不安定(?)っていうことをこんな所で実感できた。
今のところはデフォルトシェルにはせずに.bashrcとかからexecして切り替えるようにしよう。

となんとなくオチがついたように見せかけるテスト。



追記

これって結構大変なことじゃないか?
例えばPerlで動作確認しようとして-eスイッチに色々プログラムを渡したら、bashzshで解釈が違うってことだよね?
それまずくない?



やっぱりオチはない。