パラメータが空の文字列に設定されているかどうかをテストする方法は?

パラメータが空の文字列に設定されているかどうかをテストする方法は?

パラメータが空の文字列かどうかをテストしたいです""

このパラメータが設定されていないと、テストは失敗します。

  1. 次のタスクが成功しなかったのはなぜですか?

    $ unset aa
    $ if [ ${aa}=="" ]; then echo yes; else echo no; fi
    yes
    
  2. どうすればいいですか?

答え1

(試した)テストは、$aa == ""2つの空の文字列を互いに比較することによって実際の結果を生成します。これは、シェルが設定されていない変数を空の文字列に拡張するためです。周囲にスペースがない場合は、両方の==文字列のテストと同じであるため、テストは常にtrueです==。この文字列は常に真です。

代わりにbash:

$ unset aa
$ if [ -v aa ]; then echo Set; else echo Not set; fi
Not set
$ aa=""
$ if [ -v aa ]; then echo Set; else echo Not set; fi
Set

したがって、空の文字列の完全なテストは次のとおりです。

if [ -v aa ] && [ -z "$aa" ]; then
    echo Set but empty
fi

からhelp testbash

-v VARVARシェル変数が設定されている場合は真です。

またはbashマニュアルの「条件式」セクションで:

-v varname

シェル変数が設定されている場合varname(値が割り当てられている場合)真。

テストでは-v変数をテストできます。名前その価値を見るよりも


本当に文字列比較をしたい場合は、できる次のようなことをする

if [[ "${aa-InvalidValue}" != "InvalidValue" ]] && [ -z "$aa" ]; then
    echo Set but empty
fi

設定しないと、拡張子が${variable-value}拡張されます。valuevariable

非常に似た内容がif is unset${variable:-value}に拡張されます。valuevariableまたは空(空の文字列).

答え2

testつまり、[演算子の周りにスペースが必要です。そうでなければ、foo==有効な文字列であっても演算子を含むものとして扱われるからです。構造[[ .. ]]は同じように機能します。 (望むよりこの問題そしてバッシュFAQ 031[違いを比較してみてください[[。 )

そうだろ[ ${aa}=="" ]いつも[ string ]と同じなのでtrueです[ -n string ]。つまり、文字列が空でないことをテストします。ここで文字列には少なくとも==

設定されていないか空の場合は、引用符拡張子を持たない空の変数が消え、有効なテストではないため[ ${aa} == "" ]エラーが発生します。 NULL以外の値がある場合はFalseです。 (これは特別なので引用符なしで動作します。)aa[ == foo ]aa[[ ${aa} == "" ]][[ .. ]]

もちろん、同様に設定されていないか空であるかを[ "${aa}" == "" ]テストしてください。aa[ -z "${aa}" ]


空であることをテストするためにを使用するか、[ "${aa+x}" ] && [ -z "$aa" ]2つを巧妙に組み合わせることができます。@Stéphane Chazelasの返信:

if [ "${aa+x$aa}" = "x" ] ; then
    echo "aa is empty but set"
fi

aa(これは設定されていない場合は空の文字列に展開され+、設定されている場合(x$aaつまり空のx場合)に拡張されるために機能しますaa。)

$ foo() { [ "${1+x$1}" = "x" ] && echo "set but empty" || echo "unset or non-empty"; }    
$ foo; foo ""; foo bar
unset or non-empty
set but empty
unset or non-empty

答え3

==まず、周囲にスペースが必要であることを知っているとします。の使用は==bash、ksh、およびzshでのみ有効で、最もよく使用されます=。また、テスト内で拡張変数を参照する必要があります。だから私はその行が実際に次のようになると仮定します。

unset aa ; if [ "${aa}" = "" ]; then echo yes; else echo no; fi

この時点であなたの質問は次のとおりです。

次のタスクが成功しなかったのはなぜですか?

通常の unset var の拡張は null に設定された一般変数の拡張と同じであるためです ("[" が実行できるジョブテストで)。

I mean, "$aa" is the same value for both an unset aa or a null aa.

これがどのように機能するかを示すために、次のスクリプトを試してみてください(これはshであり、dash、bash、ksh、および/またはzshで同じように機能します)。

#!/bin/sh

blanktest(){
    if [ "${aa}" = "" ]; then echo "$1 yes"; else echo "$1 no"; fi
}

unset aa; blanktest unset
unset aa; aa="";  blanktest blank
unset aa; aa="e"; blanktest value

実行すると、次のものが生成されます。

$ ./script
unset yes
blank yes
value no

どうすればいいですか?

「代替値を使用」というパラメータ拡張を使用します。 :

${aa+x}

変数(nullまたは値)が設定されている場合はxが生成され、変数が設定されていない場合はnullが生成されます。

代わりにこのテストを試してください。

[ "x${aa}x" = "x${aa+x}" ] && echo yes || echo no

テストスクリプト(再度、sh互換):

#!/bin/sh

blanktest(){
    if [ "x${aa}x" = "x${aa+x}" ]; then echo "$1 yes"; else echo "$1 no"; fi
}

unset aa; blanktest unset
unset aa; aa="";  blanktest blank
unset aa; aa="e"; blanktest value

実行すると、次のように印刷されます。

$ ./script
unset no
blank yes
value no

興味があれば、いくつかの可能な変形があります。

関連情報