環境的にBashが前提になってる所がほとんどなので Zshに完全移行するつもりはないんですが、 なんとなく色々書いてたスクリプトとかをZshでも使えるようにしてみようとしたら 結構面倒だったので取り敢えず詰まったところとかについてまとめておきたいと思います。
配列の番号
基本的な部分にして最大のやっかいもの。 Bashは通常0番から配列が詰められますが、Zshでは1番から詰められます。
- Bashの場合
1 2 3 4 5 6 7 8 |
|
- Zshの場合
1 2 3 4 5 6 7 8 |
|
これを解消するためにはbashの場合にarr=("" "${arr[@]}")
みたいにして
0番に無理やり追加して1つずらす、というのも手ですが、
Zshの方で、配列を0番からに出来るksharrays
と言うオプションがあるので、そちらの方が
分かりやすいです。
スクリプトの中で、
1 2 3 4 |
|
の様にしておけばOK。 (localoptionsでその関数内だけで有効)
追記: 2017/01/23
localoptions
を使わなくても、
1
|
|
と、emulate
を使ってもその関数内で閉じる事ができます。
こちらは配列以外にも色々とkshに近づけます。
追記ここまで
グロブ展開
上のecho
時にも、Bashの場合は"
を除いても大丈夫ですが、
Zshでは[$i]
の部分をグロブ展開しようとしてそんなファイルは無い、と怒られます。
(ディレクトリにarr3
とかのファイルがもしあるならそのまま表示されますが。。。)
Zshの方がこの辺り賢くやってくれる、という点ではあるんですが、 Bashから移行した際には少し戸惑います。
これに対しては
setopt nonomatch
とnonomatch
オプションを指定するとbash
的な動作になります。
ただせっかくの機能なのでZsh使う場合には~/.zshrc
には書かずに、スクリプトでも
"
で囲ったりして使い分ける方が良いかな、と。
たまに色々なとこで使われててどうしようもない時の最終手段的なオプション。
typeset/localでの配列の初期化
Bashだと関数内とかで
local dirs=(a b c)
的に、local宣言と同時に配列を初期化することが出来ますが、 Zshだと
zsh: number expected
の様なエラーが出ます。配列として宣言するために-a
を使っても駄目。
これは仕方ないので
local -a dirs
dirs=(a b c)
の様に2段構えにしてあります。(オプションでなんとかなるのかもしれませんが)
readの引数
組み込みコマンドのread
に関して。
入力数を設定する引数はBashでは-n
なんですが、
Zshでの-n
はちょっと別の特別な用途で使われるため(man zshall
等参照)、
Bashの-n
と同様の引数は-k
になります。
1 2 3 4 5 |
|
こんな感じで使い分け。
readにReturnを渡した時
上みたいに1文字だけ入力、とした時、直ぐにReturnを押すと
Bashの場合には入力無しでc
は長さ0のNULL状態になります。
一方、Zshの場合には改行?が入力される様です(文字数1)。
改行コードとかで対応出来るのかもしれませんが、 差し当たりこんな感じでcaseとかを使うと BashでもZshでもReturnを使うことが出来ます。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
(ダブル)クォート
クォート関連で少し戸惑う所があったので。
for文等を回すときに
max=5
for ((i=0; i<max; i++));do echo $i;done
こんな感じで書こうとする時、Bashでは上の様に書いても大丈夫で、
さらに$max
、"max"
、"$max"
としてダブルクォートで囲ったりしても大丈夫。
一方、Zshの時はmax
か$max
のみが有効で
"$max"
を使うと
zsh: bad math expression: operand expected at `"5"'
となり5が数値でなく文字列として扱われておかしくなるようです。
"max"
とすると
zsh: bad math expression: operand expected at `"max"'
となりダメです。
この他にも変数展開の点でZshはより色々できるが為に 動きが違うことがあるようです。
ShellScript - シェルスクリプト(sh/bash/zsh)で変数から変数へ代入する方法について - Qiita [キータ]
command/builtin
追記: 2013/12/27
command/builtin 追加。
Bashの場合、command cd
などとすると、仮にcd
コマンドをaliasしていたり
関数で再定義していてもbuiltinの元のcd
を使います。
builtin cd
としても同じ。
これがZshの場合、buildin cd
は同様の動きをしますが、
command cd
はbuiltinコマンドを見に行かず、
もし再定義してなければ
zsh: command not found: cd
となります。
command [-pVv] command [arg ...]
Run command with args suppressing the normal shell function lookup. Only builtin commands or commands found in the PATH are executed. If the -p option is given, the search for command is performed using a default value for PATH that is guaranteed to find all of the standard utilities. If either the -V or -v option is supplied, a description of command is printed. The -v option causes a single word indicating the command or file name used to invoke command to be dis- played; the -V option produces a more verbose description. If the -V or -v option is supplied, the exit status is 0 if command was found, and 1 if not. If neither option is supplied and an error occurred or command cannot be found, the exit status is 127. Otherwise, the exit status of the command builtin is the exit status of command.
command [ -pvV ]
The command word is taken to be the name of an external command, rather than a shell function or builtin. If the POSIX_BUILTINS option is set, builtins will also be executed but certain special properties of them are suppressed. The -p flag causes a default path to be searched instead of that in $path. With the -v flag, command is similar to whence and with -V, it is equivalent to whence -v.
追記ここまで
まとめ
以下のサイトではBash/Zshに加え、Fish等も含め複数のシェルについて 幅広く比較してあります。 Bash/Zshだけ見ようと思うとちょっと冗長ですがかなり網羅してある感があります。
一応上のテストはMacで以下のバージョンを使って行いました。
- bash: 3.2.51(1)-release
- zsh: 5.0.2