LoginSignup
1
3

……君のような勘のいいZshは嫌いだよ [気をつけるべきBashとZshの違い]

Last updated at Posted at 2023-01-28

すいません、嘘つきました。Zsh大好きです。
Bashよりも使いやすい(=勘のいい)Zshが憎いです。

はじめに

先日、FishからZshに乗り換えました。
何故かと言うと、FishがPOSIX非互換だったからです。

とは言えども、 ZshもPOSIX非互換 なんですよね。まあ、POSIXモードもあるし、できうる限り対応させようという気がありそうなので、Zshを選びました。

しかし!そうは言ってもやっぱりPOSIX非互換。Bashと共同のスクリプトを使おうとすると、注意しなければならない点 が他のシェルと比べても数多くあります。

この記事では僕が引っかかったところを中心に、備忘録的にそういう点をまとめていきたいと思います。
何かあれば適宜追加していきます。

いいね、ストック等して頂けると今後の勉強の励みになります。
間違いや不足、書いておくと良いのでは?という項目などあればコメントなどでご指摘いただけると助かります。

プロンプトを格納する変数が違う

有名な話ですね。

  • Bash
    変数PS1に格納 します。プロンプト用エスケープ文字はバックスラッシュから始まる2文字です。
  • Zsh
    変数PS1もしくはPROMPTに格納 します。エスケープ文字はパーセントから始まる2文字です。

プロンプト表示前に実行するコマンドを、指定する方法が違う

  • Bash
    変数PROMPT_COMMANDにコマンドを格納 します。
  • Zsh
    関数precmdに実行内容を格納 します。

プロンプトでのANSIエスケープシーケンスの書き方が違う

これはなんでかよくわからない

  • Bash
    \[\e[値m\]と書きます。
    普通にecho -eで使うときは\[\]は不要です。

  • Zsh
    \e[値mと書きます。 ただ、色指定は%F{色番号}文字%fと書くほうがいいみたい。

sourceコマンド実行時のスクリプトファイルを指す変数が違う

参考:https://qiita.com/yudoufu/items/48cb6fb71e5b498b2532

例えば、ホームディレクトリで~/dir/script.shを読み込む際に、

$ pwd
/home/user
$ source ./dir/script.sh

を実行したときに、script.sh内で自分自身のパスを取得する時に参照する変数を例とします。

  • Bash
script.sh
echo $0 #-bash と返ってくる(失敗)
echo $BASH_SOURCE #~/dir/script.sh と返ってくる(成功)

この場合、echo $(dirname $0)とすると、~/script.shはありませんって怒られます。(←これが厄介)

  • Zsh
script.sh
echo $0 #~/dir/script.sh と返ってくる(成功)

解決法

script.sh
echo ${BASH_SOURCE:-$0}

とするといいようです。

シェルスクリプト内の関数内での$0の値が違う

これが意外と厄介だったりする

以下のスクリプトファイルにおいて、

script.sh
function() {
    echo $0
}
  • Bash
$ source script.sh #スクリプトファイルの読み込み
$ function
script.sh
  • Zsh
% source script.sh #スクリプトファイルの読み込み
% function
function

変数内の一部の文字列を抜き出すときに"最後まで"を指定する方法が違う

これでエラー出た時「だるっ」て思いました。

  • Bash
$ HOGE="HOGEHOGE"
$ echo ${HOGE:3:$ }
bash: HOGE: $: 構文エラー: オペランドが予期されます(エラーのある構文は"$"#エラーになるので、ここは普通に計算しなきゃいけない
$ echo ${HOGE:3:$((${#HOGE} - 3))}
EHOGE
  • Zsh
% HOGE="HOGEHOGE"
% echo ${HOGE:3:$ } #なんかこれで上手くいく
EHOGE

チルダ置換が違う

わっかりずら。って思いました。

  • Bash
$ whoami
user
$ echo ~
/home/user #チルダがホームディレクトリとして展開
$ echo ~user
/home/user #ホームディレクトリに展開
$ echo ~$USER
~user #変数の場合はホームディレクトリは展開されない
$ echo ~"user"
~user #クオートされていても展開されない
$ echo ~\u\s\e\r
~user #エスケープされてても展開されない
$ echo ~存在しないユーザ
~存在しないユーザ #存在しないユーザの場合そのまま
  • Zsh
% whoami
user
% echo ~
/home/user #チルダがホームディレクトリとして展開
% echo ~user
/home/user #ホームディレクトリに展開
% echo ~$USER
/home/user #ホームディレクトリに展開
% echo ~"user"
/home/user #ホームディレクトリに展開
% echo ~\u\s\e\r
/home/user #ホームディレクトリに展開
& echo ~存在しないユーザ
zsh: no such user or named directory: 存在しないユーザ #エラー

配列のインデックス番号が違う

  • Bash
$ arr=(hoge fuga piyo)
$ echo arr[1]
fuga #0から順にインデックス
  • Zsh
% arr=(hoge fuga piyo)
% echo arr[1]
hoge #1から順にインデックス

おわり

似て非なるところが多すぎて、互換性のあるスクリプトを書くのは難しいですね…
でもFishよりは扱いやすいと思います。Fish、好きなんだけどスクリプトが書けなすぎてねぇ。

Zshに関してはこれも是非是非。(ほぼ個人的備忘録ですが。)

それから、こちらの記事はBashとZshに限らずPOSIX系のシェルに関する互換性の問題をまとめて下さっていますのでこちらもご参考に!

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3