HOWTO · Bash
入力引数が Bash に存在するかどうかを確認する
このチュートリアルでは、スクリプト ユーザーが入力引数を Bash スクリプトに渡したかどうかを確認する方法について説明します。
このページの内容
Bash スクリプトの位置パラメーターを確認すると、必須の引数が渡されたかどうかを判断できます。すべての引数の個数は $# で数え、最初の引数の値が必要な場合は $1 を使います。引数なしの呼び出しを確実に拒否するには個数を確認します。$1 の確認では別のことが分かります。以下の例では、ユーザー入力に依存する処理を始める前に、この違いを踏まえて確認する方法を示します。
Bash スクリプトの引数を $# で数える
$# は、現在の関数またはスクリプトに渡された位置引数の個数に展開されます。個々の引数の値が入るわけではありません。たとえば、./script.sh one two と実行すると個数は 2 になり、引数を付けずに実行すると 0 になります。そのため、値を読み取ったり処理したりする前に、コマンドが受け取った値の個数を確認するのに $# を使えます。関数内でも同じように使えますが、その場合は関数に渡された引数の個数を表します。
値を3つ渡して、次の例を実行します。
show_arguments() {
printf 'Argument count: %s\n' "$#"
printf 'First argument: %s\n' "$1"
}
show_arguments delft stack blog
Argument count: 3
First argument: delft
1行目には値の個数が表示され、2行目には最初の値が表示されます。少なくとも1つの値が必要なスクリプトでは、引数を使うコマンドより前にガードを置きます。次のスクリプトは、ガードを通過した後で値を受け取り、引数がない場合は分かりやすいエラーを報告します。
#!/usr/bin/env bash
require_arguments() {
if (( $# == 0 )); then
printf '%s\n' 'No input arguments exist' >&2
return 1
fi
}
run_check() {
if ! require_arguments "$@"; then
return 1
fi
printf 'Received %s argument(s).\n' "$#"
printf 'First argument: %s\n' "$1"
}
run_check delft
Received 1 argument(s).
First argument: delft
この単独で実行できる例では delft を渡すため、ガードを通過し、スクリプトは個数と最初の値を報告します。コードと出力例の表示文字列は変更されておらず、英語のままです。
呼び出し元から渡された実際の引数を検証するスクリプトでは、代わりに run_check "$@" をエントリーポイントとして使います。引数がない場合、require_arguments は標準エラー出力に No input arguments exist と表示して 1 を返します。その後、run_check は最後のコマンドの結果として 1 を返すため、スクリプトも終了ステータス 1 で終了します。引数が1つ以上あれば、ガードは実行されません。メッセージを変更したり、必要な個数を増やしたりできます。たとえば値が2つ必要なら (( $# < 2 )) とします。必要な最小個数は、スクリプトの後続処理が実際に使う値に基づいて決め、ファイルの作成や設定変更などの副作用が起きる前に検証してください。
関数を呼び出すと、関数内の $# は外側のスクリプトの個数ではなく、その関数自身に渡された引数の個数を表します。関数が値を必要とする場合は、明示的に渡してください。この違いは、スクリプトに任意のフラグがあり、その一部の値だけをヘルパー関数に渡す場合に役立ちます。個数は数値なので、Bash の算術式 (( $# == 0 )) を使うと、パラメーターの文字列の内容を調べずに比較を直接表せます。
Bash の最初の引数を $1 で確認する
$1 は最初の位置パラメーターです。値を確認または表示するときは引用符で囲みます。たとえば [[ -n "$1" ]] を使うと、値が空でないか確認できます。この確認だけでは、引数が渡されたかどうかは分かりません。呼び出し元が ./script.sh '' のように最初の値として空文字列を渡しても、$# は 1 です。つまり、値に文字がなくても、その位置の引数は存在します。引数の有無には個数を使い、値の内容には値の確認を使ってください。
少なくとも1つの引数が渡されたことを確かめるには $# を使います。最初の引数に空でない値が入っていることを確かめるには、引用符で囲んだ $1 を確認します。位置パラメーター $1、$2、$3 は、それぞれ1番目、2番目、3番目の値を表します。別のコマンドに渡すときは、値に含まれる空白が分割されないよう、それぞれ引用符で囲んでください。たとえば最初の値が North Shore の場合、"$1" と囲めば、シェルによって別々の単語に分割されず、1つの値として保たれます。
両方の条件が必要な場合は、2つの確認を組み合わせられます。まず (( $# > 0 )) を確認し、次に [[ -n "$1" ]] を確認します。確認を分けると、エラーメッセージを具体的にできます。引数が省略されたことや、渡された最初の値に文字が必要なことを呼び出し元に伝えられます。最初の引数が任意の場合は個数のガードを省き、そのコマンドで値がない場合にどう扱うかを決めてください。[[ ... ]] では、明確さのため $1 を引用符で囲むことをおすすめします。ただし、この形式では単語分割やファイル名展開は発生しません。一方、単一角括弧の [ ... ] 形式では、"$1" のように展開を引用符で囲んでください。引用符がない展開では、単語分割やファイル名展開が起きることがあります。