「set -o nounset」を使用するときに変数がbashに設定されているかどうかをテストします


94

次のコードは、バインドされていない変数エラーで終了します。set -onounsetオプションを使用しながら、これを修正するにはどうすればよいですか?

#!/bin/bash

set -o nounset

if [ ! -z ${WHATEVER} ];
 then echo "yo"
fi

echo "whatever"

回答:


97
#!/bin/bash

set -o nounset


VALUE=${WHATEVER:-}

if [ ! -z ${VALUE} ];
 then echo "yo"
fi

echo "whatever"

この場合、VALUEが設定されていないと、空の文字列になりますWHATEVER。「パラメータの展開」で{parameter:-word}検索できる展開を使用していますman bash


14
[!-z $ {VALUE}]; if [!-z $ {WHATEVER:-}];
Angelom、2011年

18
:-変数が設定されていないか空かをチェックします。設定されていないかどうかだけを確認したい場合は、を使用し-ますVALUE=${WHATEVER-}。また、変数が空かどうかを確認するより読みやすい方法:if [ "${WHATEVER+defined}" = defined ]; then echo defined; else echo undefined; fi
l0b0

1
また、$WHATEVER空白のみが含まれている場合、これは機能しません-私の回答を参照してください。
l0b0

9
! -z」だけでなく「」を使用する理由はあり-nますか?
Jonathan Hartley、

31

期待する結果を得るには、変数を引用符で囲む必要があります。

check() {
    if [ -n "${WHATEVER-}" ]
    then
        echo 'not empty'
    elif [ "${WHATEVER+defined}" = defined ]
    then
        echo 'empty but defined'
    else
        echo 'unset'
    fi
}

テスト:

$ unset WHATEVER
$ check
unset
$ WHATEVER=
$ check
empty but defined
$ WHATEVER='   '
$ check
not empty

よる以外、私はこれを試してみましたが、私はこの作品を驚いている...すべてが正しいと"info bash""${WHATEVER-}"持っていなければならない":"前に(コロン)"-":のように(ダッシュ)"${WHATEVER:-}"、そして"${WHATEVER+defined}"前にコロンが必要"+"(プラス)などを:"${WHATEVER:+defined}"。私にとっては、コロンの有無にかかわらず、どちらの方法でも機能します。'nixの一部のバージョンでは、コロンを含めないと機能しない可能性があるため、おそらく追加する必要があります。
Kevin Fegan 14年

8
いや、-+:+、および:-すべてのサポートされています。前者は変数が設定されているかどうかを検出し、後者は設定されているかを検出します。From man bash:「コロンを省略すると、設定されていないパラメーターに対してのみテストが行​​われます。」
l0b0 2014年

1
Nevermind =)。あなたは正しいです。どうしてそれを逃したのかわかりません。
Kevin Fegan、2014年

docsから:別の言い方をすると、コロンが含まれている場合、オペレーターは両方のパラメーターの存在とその値がnullでないことをテストします。コロンが省略されている場合、オペレーターは存在のみをテストします。
Acumenus 2014

8

ワンライナーはどうですか?

[ -z "${VAR:-}" ] && echo "VAR is not set or is empty" || echo "VAR is set to $VAR"

-z 空または未設定の変数の両方をチェックします


2
いいえ、-z次のパラメータが空であるかどうかを確認するだけです。-zisは[コマンドの単なる引数です。変数の展開[ -zは、何でもできる前に行われます。
ドルメン2015年

1
$ VARが設定されていない場合にエラーを生成しないという点で、これは正しい解決策のようです。@dolmenは、機能しない場合の例を提供できますか?
Chris Stryczynski 2017年

@dolmenは、param展開に関するさまざまなbashリソースを読み、複雑すぎる他の回答を見つけたので、これには何の問題もありません。そのため、「明確化」は技術的には正確ですが、未設定と空を区別する必要がない限り、実際には意味がありません。私はunset、empty、non-empty(bash 4)をテストしましたが、毎回宣伝されていることをほとんど行いました。
JL Peyret、

8

仮定:

$ echo $SHELL
/bin/bash
$ /bin/bash --version | head -1
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
$ set -o nounset

非インタラクティブスクリプトでエラーを出力し、変数がnullまたは設定されていない場合に終了する場合:

$ [[ "${HOME:?}" ]]

$ [[ "${IAMUNBOUND:?}" ]]
bash: IAMUNBOUND: parameter null or not set

$ IAMNULL=""
$ [[ "${IAMNULL:?}" ]]
bash: IAMNULL: parameter null or not set

スクリプトを終了させたくない場合:

$ [[ "${HOME:-}" ]] || echo "Parameter null or not set."

$ [[ "${IAMUNBOUND:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.

$ IAMNULL=""
$ [[ "${IAMUNNULL:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.

[andの]代わりに[[andを使用することもできます]]、Bashでは後者が推奨されます。

コロンが上で何をするかに注意してください。ドキュメントから:

言い換えると、コロンが含まれている場合、演算子は両方のパラメーターの存在と、その値がnullではないことをテストします。コロンが省略されている場合、オペレーターは存在のみをテストします。

明らかに必要が-nないか、-zです。

要約すると、私は通常、単にを使用します[[ "${VAR:?}" ]]例ごとに、これはエラーを出力し、変数がnullまたは設定されていない場合に終了します。


4

使用できます

if [[ ${WHATEVER:+$WHATEVER} ]]; then

だが

if [[ "${WHATEVER:+isset}" == "isset" ]]; then

より読みやすいかもしれません。


文字列の比較では、移植性を高めるためではなく、可能であれば標準(POSIX)=演算子を使用する必要があります。==[[[
イェンス、

2
@Jens質問はbashに固有であり、bashに固有の質問が含まれset -o nounsetます。#!/bin/bashスクリプトの先頭にaを置く場合、実際にはbashの拡張機能を使用するのが最善です。
Bruno Bronosky 2017年

0

これは上記で要求されたユースケースとは厳密に一致しません、使用したい場合nounset(または-u、デフォルトの動作)にしは、説明メッセージでゼロ以外の値を終了ます。

これを理解するのに十分な時間がかかり、解決策として投稿する価値があると考えました。

終了時に何かをエコーし​​たり、クリーンアップを実行したりするだけの場合は、トラップを使用できます。

:-オペレータは、あなたがそう望むものと考えられます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.