Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

bash/zshで使える${foo:?...}記法が便利 (必須値チェックに便利)

動作確認した環境

  • 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:?}で訂正した(こちらは、定義されていても空の場合は弾く)。

参考文献

zsh.sourceforge.io

www.gnu.org

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?