unsetを使用するか、変数を空に設定するか


108

私は現在、bashテストフレームワークを作成しています。テスト関数では、標準のbashテスト([[)と定義済みのマッチャーの両方を使用できます。マッチャーは '[['のラッパーであり、戻りコードを返すほかに、何が期待されているかを示す意味のあるメッセージを設定します。

例:

string_equals() {
    if [[ ! $1 = $2 ]]; then
            error_message="Expected '$1' to be '$2'."

            return 1
    fi
}

したがって、マッチャーが使用され、失敗した場合にのみ、error_messageが設定されます。

今、ある時点で、テストが成功したかどうかをテストします。成功した場合、期待値を緑で表示し、失敗した場合は赤で表示します。

さらに、error_messageが設定されている可能性があるため、メッセージが存在するかどうかをテストし、出力してから設定を解除します(次のテストではが設定されない可能性があるためerror_message)。

if [[ $error_message ]]; then
    printf '%s\n' "$error_message"

    unset -v error_message
fi

さて、私の質問は、変数の設定を解除するか、単に ''に設定する方が良いか、

error_message=''

どちらがいいですか?実際に違いはありますか?または、メッセージが設定されたことを示すフラグを追加する必要がありますか?


1
あなたがerror_message他のものと決して比較しないならば、私はそれは問題ではないと思います。しかし、私はあなたが望むと思います[[ $error_message ]]、そうでなければあなたはリテラル文字列「error_message」が存在することをテストしています。
chepner 2012

@chepnerええ、タイプミスでした。修正しました。
ヘルパーメソッド2012

回答:


143

以下を使用している場合を除き、ほとんどの場合、違いはありませんset -u

/home/user1> var=""
/home/user1> echo $var

/home/user1> set -u
/home/user1> echo $var

/home/user1> unset var
/home/user1> echo $var
-bash: var: unbound variable

したがって、実際には、変数をどのようにテストするかによって異なります。

それが設定されている場合のテストの優先方法は次のとおりです。

[[ -n $var ]]  # True if the length of $var is non-zero

または

[[ -z $var ]]  # True if zero length

43
var=「未設定」ではありません。それは引用符で囲まれていない空の文字列です。加えてset -u:、パラメータ展開のバッシュの様々な形も未設定とNULL値を区別することができ${foo:bar}たときに、「バー」に展開するfoo「際に設定されていないが、」foonullである一方で、${foo:-bar}に展開「fooが未設定またはヌルバー」である場合。
chepner 2012

1
[[ -n $var ]]var空の文字列に設定されている場合はfalseです。
chepner 2012

1
'declare -p'を使用して変数の '存在'を確認すると、var =は 'declare-var = ""'を表示するため、unsetを使用して削除する必要があります。もちろん、読み取り専用の変数の場合は取得できません。もちろんそれを取り除く。さらに、関数内でvar = somethingを使用する場合、「local var = value」を使用すれば、「declare var = value」もローカルであるため、それを削除することを心配する必要はありません。declareの場合「declare -g var = value」を使用して明示的にグローバルに設定する必要があります。「local」を使用して明示的にローカルに設定する必要があることを宣言する必要はありません。グローバル変数は消去される/ w unsetのみです。
osirisgothra 2014年

@osirisgothra:ローカル変数の良い点。もちろん、一般に、カプセル化されるように、関数内のすべての変数を宣言(またはローカライズ)するのが最善です。
cdarke 2015年

3
@chepnerはの${foo-bar}代わりにすべきです${foo:bar}。自分でテスト:unset a; echo ">${a:-foo}-${a:foo}-${a-foo}<"
Liviu Chircu 2017年


2

したがって、配列インデックス2の設定を解除すると、基本的に配列内のその要素が削除され、配列サイズ(?)が減少します。

私は自分でテストをしました。

foo=(5 6 8)
echo ${#foo[*]}
unset foo
echo ${#foo[*]}

結果は..

3
0

したがって、配列全体の設定を解除すると、実際には完全に削除されることを明確にするだけです。


0

上記のコメントに基づいて、ここに簡単なテストがあります:

isunset() { [[ "${!1}" != 'x' ]] && [[ "${!1-x}" == 'x' ]] && echo 1; }
isset()   { [ -z "$(isunset "$1")" ] && echo 1; }

例:

$ unset foo; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's unset
$ foo=     ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
$ foo=bar  ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.