空の文字列を確認したい場合は
[ -z $mystr ]
しかし、変数がまったく定義されているかどうかを確認したい場合はどうすればよいですか?または、bashスクリプトに区別はありませんか?
あなたが求めている答えは、 Vinko の answer によって暗示されていると(明示されていない場合)考えられますが、簡単には説明されていません。 VARが設定されているが空であるか設定されていないかを区別するには、次を使用できます。
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "$VAR" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
おそらく、2行目の2つのテストを1つに組み合わせることができます。
if [ -z "$VAR" -a "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
ただし、Autoconfのドキュメントを読むと、用語を「-a
」と組み合わせることはお勧めできず、&&
と組み合わせた個別の簡単なテストを使用することをお勧めします。問題があるシステムには遭遇していません。それは、それらが以前は存在しなかったことを意味しません(しかし、それらは遠い過去にそれほど珍しくなかったとしても、おそらく最近非常にまれです)。
これらの詳細、およびその他の関連する シェルパラメーター展開 、Bashマニュアルの test
または[
コマンドおよび 条件式 を参照できます。
私は最近、この答えについて質問でメールで尋ねられました:
2つのテストを使用しますが、2番目のテストはよく理解していますが、最初のテストは理解していません。より正確には、変数展開の必要性を理解していません
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
これは同じことを達成しませんか?
if [ -z "${VAR}" ]; then echo VAR is not set at all; fi
公正な質問-答えは「いいえ、あなたのより単純な代替手段は同じことをしません」です。
テストの前にこれを書いたとします:
VAR=
テストでは「VARはまったく設定されていません」と表示されますが、私の場合は(VARは設定されているが値が空である可能性があるため、何もエコーしないため暗示的に)と表示されます。このスクリプトを試してください:
(
unset VAR
if [ -z "${VAR+xxx}" ]; then echo JL:1 VAR is not set at all; fi
if [ -z "${VAR}" ]; then echo MP:1 VAR is not set at all; fi
VAR=
if [ -z "${VAR+xxx}" ]; then echo JL:2 VAR is not set at all; fi
if [ -z "${VAR}" ]; then echo MP:2 VAR is not set at all; fi
)
出力は次のとおりです。
JL:1 VAR is not set at all
MP:1 VAR is not set at all
MP:2 VAR is not set at all
テストの2番目のペアでは、変数が設定されていますが、空の値に設定されています。これは、${VAR=value}
と${VAR:=value}
表記法の違いです。 ${VAR-value}
と${VAR:-value}
、および${VAR+value}
と${VAR:+value}
なども同様です。
Gili は answer で指摘しているように、set -o nounset
オプションを指定してbash
を実行すると、上記の基本的な答えはunbound variable
で失敗します。簡単に修正できます。
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "${VAR-}" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
または、set -o nounset
でset +u
オプションをキャンセルできます(set -u
はset -o nounset
と同等です)。
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO=""
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO="a"
~> if [ -z $FOO ]; then echo "EMPTY"; fi
~>
-zは未定義の変数に対しても機能します。未定義と定義済みを区別するには、リストされているものを使用します here または、より明確な説明があれば here 。
最もクリーンな方法は、これらの例のような拡張を使用することです。すべてのオプションを取得するには、マニュアルのパラメーター拡張セクションを確認してください。
別の単語:
~$ unset FOO
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
~$ FOO=""
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
DEFINED
デフォルト値:
~$ FOO=""
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
~$ unset FOO
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
UNDEFINED
もちろん、これらのいずれかを異なる方法で使用し、「デフォルト値」の代わりに必要な値を設定し、必要に応じて展開を直接使用します。
高度なbashスクリプトガイド、10.2。パラメータの置換:
変数$ mystrが定義されているかどうかに基づいてプログラムロジックを作成するには、次のようにします。
isdefined=0
${mystr+ export isdefined=1}
現在、isdefined = 0の場合、変数は未定義であり、isdefined = 1の場合、変数は定義されています
変数をチェックするこの方法は上記の回答よりも優れており、読みやすく、未定義の変数(set -u)
の使用時にbashシェルがエラーになるように構成されている場合、スクリプトが途中で終了します。
その他の便利なもの:
未定義の場合は$ mystrにデフォルト値7を割り当て、それ以外の場合はそのままにします。
mystr=${mystr- 7}
変数が未定義の場合、エラーメッセージを出力して関数を終了します。
: ${mystr? not defined}
ここでは、$ mystrの内容が定義されている場合にコマンドとして実行されないように、「:」を使用していることに注意してください。
テストの要約。
[ -n "$var" ] && echo "var is set and not empty"
[ -z "$var" ] && echo "var is unset or empty"
[ "${var+x}" = "x" ] && echo "var is set" # may or may not be empty
[ -n "${var+x}" ] && echo "var is set" # may or may not be empty
[ -z "${var+x}" ] && echo "var is unset"
[ -z "${var-x}" ] && echo "var is set and empty"
https://stackoverflow.com/a/9824943/14731 には、より適切な回答が含まれています(読みやすく、set -o nounset
を有効にすると動作する回答)。おおよそ次のように機能します。
if [ -n "${VAR-}" ]; then
echo "VAR is set and is not empty"
Elif [ "${VAR+DEFINED_BUT_EMPTY}" = "DEFINED_BUT_EMPTY" ]; then
echo "VAR is set, but empty"
else
echo "VAR is not set"
fi
定義されている変数をチェックする明示的な方法は次のとおりです。
[ -v mystr ]
Bash Reference Manual は、bashに関する信頼できる情報源です。
変数が存在するかどうかをテストする例を次に示します。
if [ -z "$PS1" ]; then
echo This Shell is not interactive
else
echo This Shell is interactive
fi
( セクション6.3.2 から)
開いている[
の後と]
の前の空白はオプションではないことに注意してください。
Vimユーザー向けのヒント
次のようないくつかの宣言を持つスクリプトがありました。
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
しかし、私は彼らに既存の価値を守ることを望んでいました。そこで、私はそれらを次のように書き直しました。
if [ -z "$VARIABLE_NAME" ]; then
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
fi
私は簡単な正規表現を使用してvimでこれを自動化することができました:
s/\vexport ([A-Z_]+)\=("[^"]+")\n/if [ -z "$\1" ]; then\r export \1=\2\rfi\r/gc
これは、関連する行を視覚的に選択し、:
と入力することで適用できます。コマンドバーには、:'<,'>
が事前に入力されています。上記のコマンドを貼り付けて、Enterキーを押します。
このバージョンのVimでテスト済み:
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 22 2015 15:38:58)
Compiled by [email protected]
Windowsユーザーは、異なる行末を使用する場合があります。
別のオプション: 「リスト配列インデックス」展開 :
$ unset foo
$ foo=
$ echo ${!foo[*]}
0
$ foo=bar
$ echo ${!foo[*]}
0
$ foo=(bar baz)
$ echo ${!foo[*]}
0 1
これが空の文字列に展開されるのはfoo
が設定されていないときだけなので、条件付きの文字列で確認できます。
$ unset foo
$ [[ ${!foo[*]} ]]; echo $?
1
$ foo=
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=bar
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=(bar baz)
$ [[ ${!foo[*]} ]]; echo $?
0
3.0以上のbashバージョンで利用可能
さらにこの自転車を流したくないが、追加したかった
shopt -s -o nounset
スクリプトの先頭に追加できるもので、変数がスクリプト内のどこにも宣言済みでない場合はエラーになります。表示されるメッセージはunbound variable
ですが、他の人が言及しているように、空の文字列やnull値をキャッチしません。個々の値が空でないことを確認するために、${mystr:?}
で展開されている変数をテストできます。これはドル記号展開とも呼ばれ、parameter null or not set
でエラーになります。
変数が定義されているかどうかを確認するはるかに明確な方法は次のとおりです。
var_defined() {
local var_name=$1
set | grep "^${var_name}=" 1>/dev/null
return $?
}
次のように使用します。
if var_defined foo; then
echo "foo is defined"
else
echo "foo is not defined"
fi