shellscript 上達への道
shellscript は最高だ。なぜなら、すべての OS に入っている。基本的な文法はあまり変わらず、コピペで渡せばどこでも動かせる…
そう思い始めたのは、ここ最近、仕事で使うようになってからの話で、IDE からプログラミングの世界に入った自分には、当初 shellscript は難しすぎた。
そう、これで動かないのが shellscript なのだ。 Java, Python から勉強した自分には当時、何がおきているのかわからなかった。 正しくは、
良かれと思った空白が、 shellscript では思わぬエラーになる。それが shellscript の世界なのだ。
上達への道 1 : shellcheck をインストールする。いますぐに
1brew install shellcheck
この記事を読むより先に mac なら上のコマンドで shellcheck をインストールしよう。Linux, Windows でもインストールできる。
shellcheck との出会いで shellscript の旅路は大きく変わった。最初の例も shellcheck を通すと、
1$ shellcheck hoge.sh
2
3In a.sh line 2:
4a = "hoge"
5 ^-- SC1068: Dont put spaces around the = in assignments.
とエラーを出してくれる。エディタに shellcheck のプラグインをインストールすれば、shellscript を書いている最中でも間違いに気づけるはずだ。
参考
上達への道 2 : set -eux を書こう
スクリプトを書く場合は、上記で始めよう。-e はコマンドが失敗したら(0以外で終わったら)続行させない、-u は未定義の変数を参照させない、-x は実行するコマンドを1つずつ出力する(デバッグ向け)。
1#!/bin/bash
2set -eux
3
4# パスワードなどターミナル出力してほしくない箇所は +x で除いておく
5set +x
6export $YOUR_PASS="password"
7set -x
参考
上達への道 3 : 制御構造を覚えよう
最小限の制御構造は使えたほうが楽だ。代表的なのは for, if だろう。
if
if 文では [ を使う。実はこれはコマンドなのだ。
1#!/bin/bash
2set -eux
3
4if [ -e "$HOME/Desktop" ]; then
5 echo "Desktop exists"
6fi
7
8# これに等しい
9if test -e "$HOME/Desktop"; then
10 echo "Desktop exists"
11fi
だから、if(exists(…)) を真似して if[-e ]; then のようなことはできない。コマンドを空白で分ける必要があるのだ。
(次は空白が必要なのか…と思われた、あなた。そう、それが shellscript なのです)
また、&& で AND 条件などを行いたい場合は、[[ を使うことがある。
for
DRY 原則にのっとる → Bashでいろいろループする - Qiita
ただ、業務でよく行うのは、ファイルや環境値(サーバ名など)を扱う場合だ。
こういったちょっとしたスクリプトを書くことで、社内で shell おじさんの栄えある称号をもらえたりする。
上達への道 4 : いろんなコマンドを覚えよう
「shell で上達したいなら、いろんなコマンドを覚えよう」
これこそが、僕が最も伝えたいことだ。
例えば、文字列を置換したいとする。プログラミング言語を扱っていたら、まず言語のレファレンスで string パッケージの replace メソッドを探すだろう。
しかし、shellscript ではそうではない。端末にインストールされているコマンドを組み合わせて、高度な機能を実現する。
では、文字列の置換は上記のコマンドで実現しないといけないのか? そんなことはないのだ。
場合によっては、awk, GNU 版の gawk, あるいはその他のコマンドで置換してもよい。しかも、各コマンドには多種多様なオプションが用意されており、その中で最適なものを選ぶ必要がある。
OS にデフォルトで含まれていないコマンドを利用することももちろんある。例えば、json 文字列を扱うなら、多くの人は jq コマンドを利用するだろう。
shellscript の旅路は、インストールされているコマンドとの旅路と言って良い
参考
まとめ
shellscript はその癖がわかってくると、意外とあっさり書き始めることができる。
細かい作業の繰り返し、ちょっとしたサーバでの作業を shell におこして、この長い旅路を続けよう。