今回はプログラミング言語というよりコマンドシェルとして人気の高いzsh(Z Shell)について紹介します。zshは最新のmacOS Catalinaでデフォルトのシェルとなったことで話題となっています。zshは拡張性が高くさまざまな補完機能があり便利なプラグインも多く存在します。今回は、zshについて紹介します。
コマンドシェルとは何か?
そもそも『シェル(Shell)』とは何でしょうか。シェルとは、コンピューターのユーザーとがOSとコマンドを介して対話するためのインターフェイスを提供するものです。弁当屋に例えるなら、ユーザーが弁当を買う人、OSが弁当を作る人、そしてシェルは注文を聞いて厨房に伝える人です。WindowsであればコマンドプロンプトかPowerShell、macOSであればターミナル.appを起動すると、コマンドシェルを利用できます。一般的には、システム管理者やプログラマーなどが利用します。
それで、今回、macOS Catalinaで標準シェルに採用されたというのは、どういうことかと言うと、macOSでターミナル.appを開いた時に、起動するログインシェルが「bash」から「zsh」に変更になったということです。ただし、それはmacOSを新規インストールした場合で、macOSをアップグレードした場合には、bashのままとなっています。
とは言え、シェルとしてbashもzshも大きな違いがあるわけではありません。bashで利用していたシェルスクリプトの大半はzshでも利用することができます。それは、bashもzshも、多くのUnix系システムで使われていたシェル「Bourne Shell」を基にして開発されているからです。Bourne Shellは、1977年にAT&Tベル研究所で開発されUnixと共に広く使われました。それで、zshもBourne Shellの拡張版と言うことができます。
zshの特徴は?
zshはbashに比べて多機能です。他のいろいろなシェルの良いところを多く取り込んでおり、カスタマイズ性が高いことも特徴の一つです。便利な機能を列挙してみましょう。
- 補完機能が充実している
- 打ち間違えたコマンドの綴り修正候補が出る
- bash互換モードがある
- ワイルドカードを展開するファイルグロブの機能がある
- プラグインの仕組みがあり
- 手軽に環境構築するフレームワークがある
このように、いろいろな機能があります。例えば、補完機能について見てみましょう。最初の数文字を入力して[Tab]キーを押すと、コマンド名を補完してくれます。これは、bashにも付いている機能です。しかし、zshでは、コマンド名に続いて、[Tab]キーを押すと利用可能な引数の一覧を表示することができます。
また、手軽に環境を構築できるフレームワークには「oh-my-zsh」や「prezto」「zplug」などがあります。こうしたフレームワークを導入すると、画面のデザインなどを手軽に切り替えることができます。以下は、preztoを利用してプロンプトのテーマを選択しているところです。
プログラミング言語としてのzsh
そして、zshの拡張性の高さを支えているのが、プログラミング言語としての「zsh」です。zshの多彩な補完機能も自身のプログラムによって実現されています。
それで、zshの実力を示すプログラムにテトリスもどきがあります。以下のゲーム画面は、zshに標準で含まれているものです。もちろん、zshはオープンソースなのでこのゲームのコードも見ることができます。この点でも、zshのスクリプト機能の自由度の高さを垣間見ることができるでしょう。
こちらがテトリスのソースコードです。
そもそも、このゲームがzshに標準で含まれることになった理由が、このコードの冒頭に書かれています。「Emacsのようにテトリスやアドベンチャーゲームがないから駄目だ」と批判されたことがきっかけになったのだとか。確かに、このおまけ機能が、zshにもテキストエディタで自由度の高いEmacsのような表現力があることを示しています。
zshでFizzBuzz問題を解く
次に、本連載で毎回作っているFizzBuzzのプログラムを見てみましょう。FizzBuzz問題とは、以下のような問題です。
> 1から100までの数を出力するプログラムを書いてください。ただし、3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」と表示してください。3と5の倍数の時は「FizzBuzz」と表示してください。
FizzBuzz問題は、繰り返し構文や条件分岐など、プログラミングの基本要素を理解していないと解けないので、プログラム言語の本質を掘り下げるのに適した問題です。それでは、さっそく確認してみましょう。
#!/bin/zsh
# FizzBuzzの値を返す関数を定義 --- (*1)
function fizzbuzz {
if (( $1 % 15 == 0 )) {
echo FizzBuzz
} elif (( $1 % 3 == 0 )) {
echo Fizz
} elif (( $1 % 5 == 0 )) {
echo Buzz
} else {
echo $1
}
}
# 100回繰り返す --- (*2)
for i in {1..100}; do
fizzbuzz $i
done
上記のプログラムを「fizzbuzz.sh」という名前で保存します。そして、zshを動かしているシェルで次のコマンドを実行します。
chmod 766 fizzbuzz.sh
./fizzbuzz.sh
すると、以下のように、FizzBuzzの結果を表示します。
プログラムを確認してみましょう。プログラムの(*1)の部分では、FIzzBuzzの値を返す関数を定義しています。関数を記述するのに『function xxx { ... }』と書けたり、条件分岐を記述『if (( ... )) { ... }』のような書式で書けたり、プログラマーにとって馴染みのある記法で記述できます。次に、(*2)の部分では、for構文を利用して繰り返し処理を記述しています。
シェルスクリプトと言うと、少し特殊な記法で記述しなくてはならないものという印象がありますが、比較的読みやすいのではないでしょうか。
まとめ
以上、今回は、zshについて簡単に紹介しました。プログラムや設定によってさまざまなカスタマイズができる点も簡単に確認できました。とは言え、zshは非常に奥が深いので、なかなか全貌をお伝えできないのが残念です。今回、macOS Catalinaにアップデートして、zshを始めたという方も多いことでしょう。筆者自身もまだzshに移行したばかりなので、その道の達人たちから少しずつ教えを受けてきたいと思っているところです。
自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。