web-dev-qa-db-ja.com

文字列がbashシェルスクリプトで定義されていないかどうかを確認する方法は?

空の文字列を確認したい場合は

[ -z $mystr ]

しかし、変数がまったく定義されているかどうかを確認したい場合はどうすればよいですか?または、bashスクリプトに区別はありませんか?

148
SetJmp

あなたが求めている答えは、 Vinkoanswer によって暗示されていると(明示されていない場合)考えられますが、簡単には説明されていません。 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}なども同様です。


Gilianswer で指摘しているように、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 nounsetset +uオプションをキャンセルできます(set -uset -o nounsetと同等です)。

134
~> 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

もちろん、これらのいずれかを異なる方法で使用し、「デフォルト値」の代わりに必要な値を設定し、必要に応じて展開を直接使用します。

37
Vinko Vrsalovic

高度なbashスクリプトガイド、10.2。パラメータの置換:

  • $ {var + blahblah}:varが定義されている場合、式に 'blahblah'が代入され、そうでない場合はnullが代入されます
  • $ {var-blahblah}:varが定義されている場合、それ自体が置換されます。それ以外の場合は、 'blahblah'が置換されます
  • $ {var?blahblah}:varが定義されている場合、置換されます。それ以外の場合、エラーメッセージとして 'blahblah'を含む関数が存在します。


変数$ mystrが定義されているかどうかに基づいてプログラムロジックを作成するには、次のようにします。

isdefined=0
${mystr+ export isdefined=1}

現在、isdefined = 0の場合、変数は未定義であり、isdefined = 1の場合、変数は定義されています

変数をチェックするこの方法は上記の回答よりも優れており、読みやすく、未定義の変数(set -u)の使用時にbashシェルがエラーになるように構成されている場合、スクリプトが途中で終了します。


その他の便利なもの:

未定義の場合は$ mystrにデフォルト値7を割り当て、それ以外の場合はそのままにします。

mystr=${mystr- 7}

変数が未定義の場合、エラーメッセージを出力して関数を終了します。

: ${mystr? not defined}

ここでは、$ mystrの内容が定義されている場合にコマンドとして実行されないように、「:」を使用していることに注意してください。

17
user854270

テストの要約。

[ -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"
9
k107

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
5
Gili

定義されている変数をチェックする明示的な方法は次のとおりです。

[ -v mystr ]
4
Felix Leipold

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ユーザーは、異なる行末を使用する場合があります。

1
funroll

別のオプション: 「リスト配列インデックス」展開

$ 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バージョンで利用可能

1
Aaron Davies

さらにこの自転車を流したくないが、追加したかった

shopt -s -o nounset

スクリプトの先頭に追加できるもので、変数がスクリプト内のどこにも宣言済みでない場合はエラーになります。表示されるメッセージはunbound variableですが、他の人が言及しているように、空の文字列やnull値をキャッチしません。個々の値が空でないことを確認するために、${mystr:?}で展開されている変数をテストできます。これはドル記号展開とも呼ばれ、parameter null or not setでエラーになります。

1
Sacrilicious

変数が定義されているかどうかを確認するはるかに明確な方法は次のとおりです。

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
0
Swiss