web-dev-qa-db-ja.com

変数が「if」ステートメントに存在するかどうかを確認するにはどうすればよいですか?

ifステートメントで変数の存在を確認する必要があります。以下の影響があるもの:

if [ -v $somevar ]
then
    echo "Variable somevar exists!"
else
    echo "Variable somevar does not exist!"

そして、それに最も近い質問は this で、実際には私の質問に答えていません。

74
Interesting...

最新のbash(バージョン4.2以降):

[[ -v name_of_var ]]

help testから:

-v VAR、シェル変数VARが設定されている場合はTrue

103
Chris Down

existsの意味に依存します。

宣言されているが割り当てられていない変数は存在しますか

空のリストが割り当てられている配列(またはハッシュ)変数は存在しますか

現在割り当てられていない変数を指すnameref変数は存在しますか

$-$#$1変数を考慮しますか? (POSIXはしません)。

ボーンのようなシェルでは、標準的な方法は次のとおりです。

if [ -n "${var+set}" ]; then
  echo '$var was set'
fi

これは、スカラー変数やその他のパラメーターに対して機能し、変数に値が割り当てられているかどうかを示します(空、自動的、環境、割り当て、readforなどから)。

typesetまたはdeclareコマンドがあるシェルの場合、setであった変数として報告されませんdeclaredただし、assignedzshを除き。

配列をサポートするシェルの場合、yashzshを除き、要素がないとset配列変数として報告されません。 of indice 0が設定されています。

bashksh93zshも除く)の場合、連想配列型の変数の場合、キー「0」の要素が設定されていない限り、setとしてレポートされません。

ksh93およびbashの場合、タイプnamerefの変数の場合、namerefによって参照される変数がそれ自体はsetと見なされます。

kshzshおよびbashの場合、より優れたアプローチは次のとおりです。

if ((${#var[@]})); then
  echo '$var (or the variable it references for namerefs) or any of its elements for array/hashes has been set'
fi

ksh93zsh、およびbash 4.4以降の場合、次のものもあります。

if typeset -p var 2> /dev/null | grep -q '^'; then
  echo '$var exists'
fi

設定または宣言された変数を報告します。

28

[〜#〜] so [〜#〜] の回答で述べたように、次の方法で確認できます。

if [ -z ${somevar+x} ]; then echo "somevar is unset"; else echo "somevar is set to '$somevar'"; fi

ここで、$ {somevar + x}は、varが設定されていない場合はnullと評価され、それ以外の場合は文字列 "x"に置き換えられるパラメーター展開です。

他の回答で提案されているように-nを使用すると、変数に空の文字列が含まれているかどうかのみがチェックされます。それはその存在をチェックしません。

10
shivams

POSIXly:

! (: "${somevar?}") 2>/dev/null && echo somevar unset

または、シェルにメッセージを表示させることもできます。

(: "${somevar?}")
zsh: somevar: parameter not set
4
cuonglm
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi
3
Mel
printf ${var+'$var exists!\n'}

...印刷しない場合は何も印刷しません。または...

printf $"var does%${var+.}s exist%c\n" \ not !

...どちらかの方法で教えてくれます。

テストの戻り値を使用して、条件に適したフォーマット文字列に動的に展開できます。

[ "${var+1}" ]
printf $"var does%.$?0s exist%c\n" \ not !

置換に基づいてprintfを失敗させることもできます...

printf $"var does%${var+.}s exist%c\n%.${var+b}d" \
        \ not ! \\c >&"$((2${var+-1}))" 2>/dev/null

...これは$var does not exist!をstderrに送信し、$varは設定されていませんが、出力$var does exist!を標準出力に追加し、$varが設定されています。

2
mikeserv

この単純な行は機能します(そしてほとんどのPOSIXシェルで機能します)。

${var+"false"} && echo "var is unset"

または、長い形式で記述します。

unset var

if ${var+"false"}
then
   echo "var is unset"
fi

拡張は次のとおりです。

  • Varに値(nullでも)がある場合、falseが置き換えられます
  • Varに「値なし」がある場合、「値なし」(null)が置き換えられます。

${var+"false"}展開は、「null」または「false」のいずれかに展開されます。
次に、「nothing」または「false」が実行され、終了コードが設定されます。

コマンドtest[または[[)は、拡張自体(の実行)によって終了値が設定されるためです。

1
user79743

bashscalarおよびarrayタイプの両方で機能する関数:

定義

has_declare() { # check if variable is set at all
    local "$@" # inject 'name' argument in local scope
    &>/dev/null declare -p "$name" # return 0 when var is present
}

呼び出し

if has_declare name="vars_name" ; then
   echo "variable present: vars_name=$vars_name"
fi
0

純粋なシェルの方法:

[ "${var+1}" ] || echo "The variable has not been set"

テストスクリプト:

#!/bin/sh
echo "Test 1, var has not yet been created"
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 2, var=1"
var=1
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 3, var="
var=
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 4, unset var"
unset var
[ "${var+1}" ] || echo "The variable has not been set"
echo "Done"

結果:

Test 1, var has not yet been created
The variable has not been set
Test 2, var=1
Test 3, var=
Test 4, unset var
The variable has not been set
Done
0

Bash 4.4.19では、以下がうまくいきました。ここに完全な例があります

$export MAGENTO_DB_Host="anyvalue"

#!/bin/bash

if [ -z "$MAGENTO_DB_Host" ]; then
    echo "Magento variable not set"
else
    echo $MAGENTO_DB_Host
fi
0
Aftab Naveed

変数が宣言/設定解除されているかどうかをチェックする関数

空を含む$array=()


@ Gillesの answer に加えて

_case " ${!foobar*} " in
  *" foobar "*) echo "foobar is declared";;
  *) echo "foobar is not declared";;
esac
_

-関数内にカプセル化する方法が見つかりませんでした-部分的に Richard Hansen に基づいた単純なバージョンを追加したいと思います answer ですが、空のarray=()で発生する落とし穴にも対処します。

_# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
_
  • 変数が設定されている(設定されていない)かどうかを最初にテストすることにより、必要でない場合は、宣言の呼び出しを回避できます。
  • ただし、_$1_に空の$array=()の名前が含まれている場合、宣言を呼び出すと、正しい結果が得られます
  • 変数が設定されていないか空の配列の場合にのみ宣言が呼び出されるため、/ dev/nullに渡されるデータは多くありません。


次のコードで関数をテストできます:

_( # start a subshell to encapsulate functions/vars for easy copy-paste into the terminal
  # do not use this extra parenthesis () in a script!

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}

:;       echo -n 'a;       '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=;      echo -n 'a=;      '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a="sd";  echo -n 'a="sd";  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=();    echo -n 'a=();    '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=("");  echo -n 'a=("");  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
unset a; echo -n 'unset a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
echo ;
:;       echo -n 'a;       '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=;      echo -n 'a=;      '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a="foo"; echo -n 'a="foo"; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=();    echo -n 'a=();    '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=("");  echo -n 'a=("");  '; var_is_unset a && echo "# is unset" || echo "# is not unset"
unset a; echo -n 'unset a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
)
_

スクリプトは戻るはずです

_a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset
_
0
Martin Rüegg

ifコマンドを使用してbashで宣言された変数の存在を確認することはできませんが、新しいbashには-vオプションが存在しますが、移植性がなく、古いbashバージョン。なぜなら、存在しない変数を使用しているとき、それは同時に生まれるからです。

例えば。 MYTEST変数に値を使用したり割り当てたりしなかったとしますが、echoコマンドを使用すると何も表示されません。または、if [ -z $MYTEST ]を使用している場合、ゼロの値が返されました。この変数が存在しないことを示す別の終了ステータスは返されませんでした!

これで2つの解決策があります(-vオプションなし):

  1. declareコマンドを使用します。
  2. setコマンドを使用します。

例えば:

MYTEST=2
set | grep MYTEST
declare | grep MYTEST

しかし、残念ながら、これらのコマンドはメモリに関数をロードしたことも示しています!よりきれいな結果を得るには、declare -p | grep -q MYTEST ; echo $?コマンドを使用できます。

0
Sepahrad Salour