パラメータ拡張
明白な答えは、パラメーター展開の特殊な形式の1つを使用することです。
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
または、より良い(下記の「二重引用符の位置」のセクションを参照):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
最初のバリアント(単にを使用?
)ではSTATEを設定する必要がありますが、STATE = ""(空の文字列)は問題ありません。正確には望みどおりではなく、代わりの古い表記法です。
2番目のバリアント(を使用:?
)では、DESTを設定し、空にする必要があります。
メッセージを指定しない場合、シェルはデフォルトのメッセージを提供します。
この${var?}
構成は、バージョン7 UNIXおよびBourne Shell(1978年前後)に移植可能です。${var:?}
私はそれが1981年ごろシステムIII UNIXでだったと思うが、それはその前のPWB UNIXにされていることがあります。構文は少し最近のことです。したがって、それはKornシェルと、特にBashを含むPOSIXシェルにあります。
通常は、シェルのマニュアルページの「パラメーター拡張」というセクションに記載されています。たとえば、bash
マニュアルは言う:
${parameter:?word}
NullまたはUnsetの場合はエラーを表示します。パラメータがnullまたは未設定の場合、単語の展開(または単語が存在しない場合はその旨のメッセージ)が標準エラーに書き込まれ、対話型でない場合はシェルが終了します。それ以外の場合は、パラメーターの値が置き換えられます。
コロンコマンド
おそらく、colonコマンドは単に引数が評価されて成功することを付け加えておきます。これは、元のシェルコメント表記です( ' #
'の前から行末まで)。長い間、Bourneシェルスクリプトの最初の文字はコロンでした。Cシェルはスクリプトを読み取り、最初の文字を使用して、Cシェル( ' #
'ハッシュ)とBourneシェル( ' :
'コロン)のどちらであるかを判断します。次に、カーネルはその行為に参加し、 ' #!/path/to/program
'のサポートを追加し、Bourneシェルは ' #
'コメントを取得しました。しかし、コロンで始まるスクリプトに出くわした場合は、その理由がわかります。
二重引用符の位置
コメントで質問されたblong:
この議論についての考えは?https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
議論の要点は:
…ただし、shellcheck
バージョン0.4.1を使用すると、次のメッセージが表示されます。
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
この場合、どうすればいいですか?
短い答えは「shellcheck
提案どおりに行う」です。
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
その理由を説明するために、以下を検討してください。注意:
コマンドには、引数をエコーしません(ただし、シェルは引数を評価しません)。引数を見たいので、以下のコードprintf "%s\n"
はの代わりに使用し:
ます。
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
式全体が二重引用符で囲まれていない場合、の値が$x
最初に展開され*
、次にファイル名のリストに展開されることに注意してください。これはshellcheck
修正すべき推奨事項です。式が二重引用符で囲まれているフォームに反対しないことは確認していませんが、問題がないことは妥当な前提です。