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

StackOverflow https://stackoverflow.com/questions/228544

質問

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

[ -z $mystr ]

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

役に立ちましたか?

解決

Vinko 答え。ただし、簡単に説明されているわけではありません。 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」と組み合わせることをお勧めせず、&&と組み合わせた個別の簡単なテストを使用することをお勧めします。問題があるシステムには遭遇していません。それは、それらが以前は存在しなかったことを意味しません(しかし、それらは遠い過去にそれほど珍しくなかったとしても、おそらく最近非常にまれです)。

これらの詳細、およびその他の関連するシェルパラメータ展開 testまたは< => コマンドおよび条件式 Bashマニュアルの


最近、この回答について質問でメールで質問されました:

  

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=

テストでは<!> quot; VARはまったく設定されていません<!> quot;と表示されますが、私のテストでは(何もエコーしないため、暗示的に)<!> quot; VARは設定されていますが、値が空の場合があります<!> quot;。このスクリプトを試してください:

(
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}なども同様です。


Gili が彼の回答${VAR:+value}オプションを指定してbashを実行すると、上記の基本的な回答はset -o nounsetで失敗します。簡単に修正できます:

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

またはunbound variableset +uオプションをキャンセルできます(set -uは<=>と同等です)。

他のヒント

~> 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は未定義の変数に対しても機能します。未定義と定義済みを区別するには、こちらのリストを使用するか、より明確な説明を使用します、こちら

最もクリーンな方法は、これらの例のように拡張を使用することです。すべてのオプションを取得するには、マニュアルのパラメーター拡張セクションを確認してください。

代替語:

~$ 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。パラメータの置換:

  • $ {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の内容がコマンドとして実行されないように「:」を使用していることに注意してください。

テストの要約。

[ -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 ]

別のオプション: <!> quot;リスト配列インデックス<!> quot;展開

$ 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

bashバージョン<!> gt; = 3.0で利用可能になります

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

shopt -s -o nounset

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

Bashリファレンスマニュアルは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 root@apple.com

Windowsユーザーは、異なる行末を使用する場合があります。

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

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

引数なしの呼び出しセット。定義されたすべての変数を出力します。
リストの最後のものはスクリプトで定義されたものです。
そのため、その出力を、定義されているものと定義されていないものを把握できるものにパイプすることができます

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top