[解決済み] Unixのシェルスクリプトで環境変数が設定されていることを確認する簡潔な方法は何ですか?
質問
私はいくつかのUnixシェルスクリプトを持っていて、何かを始める前に特定の環境変数が設定されていることを確認する必要があるので、このようなことを行っています。
if [ -z "$STATE" ]; then
echo "Need to set STATE"
exit 1
fi
if [ -z "$DEST" ]; then
echo "Need to set DEST"
exit 1
fi
というのは、多くのタイピングが必要です。環境変数のセットが設定されているかどうかをチェックするための、もっとエレガントなイディオムはないでしょうか?
EDIT: これらの変数には意味のあるデフォルト値がないことを明記しておきます - どれかが未設定の場合、スクリプトはエラーになるはずです。
どのように解決するのですか?
パラメータ展開
明白な答えは、パラメータ拡張の特別な形式の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=""(空文字列)でもOKです - 正確にあなたが望むものではありませんが、代替となる古い記法です。
2つ目のバリエーションは
:?
) DESTが設定され、空でないことが必要です。
メッセージを指定しない場合、シェルはデフォルトのメッセージを提供します。
は
${var?}
は、UNIX のバージョン 7 と Bourne Shell (1978 年頃) にまで遡って移植可能です。 そのため
${var:?}
という構文は、もう少し新しいものです。1981年ごろのSystem III UNIXにあったと思いますが、それ以前からPWB UNIXにあったかもしれません。 そのため、Kornシェルや、BashをはじめとするPOSIXシェルにも含まれている。
通常、シェルの man ページにある
パラメータ展開
. 例えば
bash
のマニュアルにはこうあります。
${parameter:?word}
Nullまたは未設定の場合、エラーを表示する。 パラメータが NULL または未設定の場合、word の展開(word が存在しない場合はその旨のメッセージ)を標準エラーに書き出し、シェルが対話型でない場合は終了します。 それ以外の場合は,パラメータの値が代入されます。
Colonコマンド
コロンコマンドは、単に引数が評価されて成功するものであることを付け加えておく。 これは、シェルのコメント記法の原型となるものです('
#
' から行末まで)。 長い間、ボーンシェルのスクリプトは、最初の文字にコロンを使っていました。 Cシェルはスクリプトを読んで、その最初の文字でCシェル用かどうかを判断していた('
#
' ハッシュ)または Bourne シェル('
:
コロン)。 その後、カーネルがこの動きに加わり、'
#!/path/to/program
を取得し、ボーンシェルが'
#
というコメントが出て、コロンの慣習は廃れていきました。 しかし、もしあなたがコロンで始まるスクリプトに出会ったら、その理由がわかるでしょう。
二重引用符の位置
この議論について、何かご意見はありますか? 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
は修正することを推奨しています。 式がダブルクォーテーションで囲まれた形でも異議を唱えないかどうかは検証していませんが、問題ないだろうと考えるのが妥当でしょう。
関連
-
[解決済み】shでJenkinsのステージから他のステージに変数を渡す
-
[解決済み] bash スクリプトを実行している docker エントリポイントに "permission denied" が表示される。
-
[解決済み] Bashシェルスクリプトでディレクトリが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashシェルスクリプトの入力引数の存在確認
-
[解決済み] シェルスクリプトでブール変数を宣言して使用するにはどうすればよいですか?
-
[解決済み] 特殊なドル記号のシェル変数とは何ですか?
-
[解決済み] キーと値のペアのファイルから環境変数を設定する
-
[解決済み] Unixシェルスクリプトは、スクリプトファイルが存在するディレクトリを見つけることができますか?
-
[解決済み] UnixのコンソールやMacのターミナルでシェルスクリプトを実行するには?
-
[解決済み] [Solved] awk スクリプトでシェル変数を使うには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】SEDをワイルドカードで使用する場合
-
[解決済み] Bash/Terminalで複数行の環境変数を書き出す方法 例: RSA秘密鍵
-
[解決済み] プロジェクトからすべての .pyc ファイルを削除するにはどうすればよいですか?
-
[解決済み] Bashで最新のディレクトリを変数に取得する
-
[解決済み] cygwin の ssh が終了時に "Killed by signal 1" と表示される
-
[解決済み] ファイル内の大文字・小文字を区別しない文字列を grep するには?
-
[解決済み] bashでのDiffコマンド
-
[解決済み] IPアドレスのまとめ方
-
[解決済み] Grep 'binary file matches'. どうすれば正常なgrepの出力が得られるか?[重複]する
-
[解決済み] bashの"-ne "はどういう意味ですか?