動作確認した環境
- zsh 5.9 (x86_64-pc-linux-gnu)
- GNU bash, version 4.4.23(1)-release (x86_64-suse-linux-gnu)
前置き
シェル変数の展開でよく使う記法といったらだいたい${foo:-bar}
(fooが空ならbar
を代わりに使う)で、以下のように使うことが多い。
foo=${foo:-default}
こう書くことでデフォルト値を埋められる。
また他にも、特定のパターンの左右を取り除く${foo#...}
や${foo%...}
もあって、例えばorg/repo
といったGitHubのリポジトリの文字列からorg
だけ、またはrepo
だけ取り出すというときに便利。
orgrepo="org/repo" org=${orgrepo%/*} # => org repo=${orgrepo#*/} # => repo
これは、変数を示す$
のキーボードの位置に注目して、それよりも左にある#
は左を消去し、右にある%
は右を消去する、と考えると覚えられる。
本題
で、前掲の${foo#...}
の使い方は左右どっちを消去するのだったっけと調べていると、面白そうな展開をマニュアル上に見付けた。
${foo:?メッセージ}
と書くと、$foo
が空のときメッセージ
を表示してシェルを終了(exit 1
)してくれるらしい。これは引数が必須のときに使えるはずで、以下の2つのスクリプトはおおむね等価だ。
if [[ -z "$foo" ]]; then echo "Please specify foo" exit 1 fi
$foo=${foo:?Please specify foo}
ちなみに後者は出力としてbash: foo: Please specify foo
という出力になるので、厳密には同じ表示にはならないが、だいたい同じ目的に使うことができる。
必須の変数をチェックするというパターンは頻出なはずなので、これは覚えておくとよさそう。
追記
${foo?}
の場合は、変数が定義されていて空の場合に素通りしてしまうので、${foo:?}
で訂正した(こちらは、定義されていても空の場合は弾く)。