プログラミング
シェルコロンは何もせず、それでも使う
A shell colon does nothing. Use it anyway (refp.se)
要約
シェルスクリプトにおけるコロン(:)の意外な有用性について解説した記事です。コロンは何も実行しないヌルコマンドとして機能し、特にパラメータ展開と組み合わせることで、引数の必須チェックなどを簡潔に記述できることを紹介しています。これにより、コードの可読性と効率性が向上します。
全文翻訳
シェルコロンは何もせず、それでも使う。
私は数え切れないほどのシェルスクリプトを書いてきましたが、今でも信じられないほど驚くようなトリックに出くわすことがあります。最近、私の度肝を抜いたのは、シェルのコロンです。
Published23 July 2026 at 03:53 UTC
Modified26 July 2026 at 05:33 UTC
AuthorFilip Roséen
Tags#shell#posix#unix
Table of Contents
In a land far-far away..
Checking for required arguments
Parameter expansion and the story of :?
That.. other colon
More colons in the limelight
Con-colon-sion
Frequently Asked Questions
Why do I need the null-command? Doesn't the expansion happen without the colon?
Why use the null-command when I could do VAR=${VAR:-default-value}?
In a land far-far away..
昔々、とても寒いコーヒーカップと淹れたての熱すぎるコーヒーカップがありました。4つの異なるターミナルがあり、そのうち3つは1時間前に閉じることができたはずです。そして、私が本当に(本当に)書きたくなかったシェルスクリプトがありました。たった1つのコロンが、一日(夜)を救うことになるなんて、誰が想像したでしょうか?
注:すぐに驚きたいですか? More colons in the limelight を参照してください。
Checking for required arguments
これはよく知られたダンスであり、ほとんど筋肉の記憶になっています。スクリプトがあり、いくつかの引数を取りますが、そのうちいくつかは必須です。いつものようにif文を使います。
if [ -z "$1" ]; then
echo "missing argument, aborting."
1>&2
exit 1
fi
echo "Hello $1!"
しかし…上記の4行がたった1行に置き換えられると言ったらどうでしょう?
: "${1:?missing argument, aborting.}"
echo "Hello $1!"
$ bash example.sh
example.sh: line 1: 1: missing argument, aborting.
$ bash example.sh refp
Hello refp!
そして、適切な名前の変数に参照した場合に何が起こるか見てみましょう。以前と同じ動作ですが、より見つけやすくなっています。診断メッセージに変数名が含まれています!
: "${GREET_NAME:?missing argument, aborting.}"
echo "Hello $GREET_NAME!"
$ bash greet.sh
greet.sh: line 1: GREET_NAME: missing argument, aborting.
Parameter expansion and the story of :?
前のスニペットでは2つのことが起こっています。1つはパラメータ展開を使用していると特定した方は正しいです。
構文 ${name:?diagnostic} は、$name が設定されていないか空であるかどうかをチェックします。もしそうであれば、diagnostic が標準エラー出力に表示され、シェルは非ゼロステータスで終了します。そうでなければ、$name と同等です。
That.. other colon
それは1つのコロンですが、もう1つのコロン、行の先頭に単独で座っているコロンはどうでしょうか?
: はヌルコマンドです。引数を評価して結果を破棄するだけの組み込みコマンドです。
: は古く、1971年のThompson shellまで遡ります。当時はラベルとしても、Unix初のコメントマーカーとしても機能していました。
: 暗闇の中であなたを愛を込めて見つめる2つの目。
More colons in the limelight
おそらく、: には見た目以上のものがあることはすでに確立されているかもしれませんが、ヌルコマンドの本当の魔法を証明するために、私の度肝を抜いたいくつかの使用例を挙げます。
: "${DATA_DIR:=/var/data}" # デフォルトを設定、: は結果を飲み込む
: "${RETRIES:=3}" # コマンドとして実行する代わりに
: > error.log # error.log を切り捨てる
: > error.log > access.log # error.log と access.log の両方を切り捨てる
( : < dataset.json ) && echo YES # dataset.json は読み取り可能か?
( : >> result.json ) && echo YES # result.json は書き込み可能か?
trap : INT # trap はコマンドを必要とする
sleep 60 # sleep は割り込み可能
set -u # 未設定の変数はエラーにする
: "$DEPLOY_ENV" "$HOST" # DEPLOY_ENV と HOST をチェック
if some-command; then
: # コマンドが必要
else
echo "command failed"
fi
Con-colon-sion
ですから、もしあなたが私と同じように、タイピングを少なくしたい(速く行きたい)のであれば、コーヒーが冷める前にヌルコマンドとパラメータ展開のペアを学ぶ価値はあります。
set
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
while :
colons are more than "${1:?magic}" # この例はローカルで安全に実行できます、試してみてください!
do
echo "$*" && shift
done
注:上記の例はローカルで安全に実行できます、試してみてください!
Frequently Asked Questions
オンラインでコメントをいくつか読んだ後、説明する価値のあるいくつかの点を省略したようです。質問が出てくるたびに、このセクションを更新していきます。
Why do I need the null-command? Doesn't the expansion happen without the colon?
パラメータ展開はどちらにしても行われますが、ヌルコマンドやそれに類する使用法がない場合、シェルはその結果の文字列をコマンドとして扱います。
% ${HELLO:=123}
zsh: command not found: 123
パラメータ展開をヌルコマンドでプレフィックスすると、結果は破棄されますが、式は評価されます(HELLO が 123 に設定されます)。
% : ${HELLO:=123}
% echo $HELLO
123
Why use the null-command when I could do VAR=${VAR:-default-value}?
これは基本的に個人の好みに尽きますが、愛すべきコロンを使用することで、潜在的なタイプミスを1つ(2つではなく)に減らすことができます。
: "${DATA_DIR:=/var/data}" # <- DATA_DIR は1回言及(1)
DATA_DIR="${DATA_DRI:-/var/data}" # <- おっと(2)