配列 Bash で変数が設定されているかどうかを確認する方法は?




シェルスクリプト 変数 null 代入 (24)

変数がBashに設定されているかどうかを知るには?

たとえば、ユーザーが最初のパラメータを関数に渡したかどうかを確認するにはどうすればよいですか?

function a {
    # if $1 is set ?
}

case "$1" in
 "") echo "blank";;
 *) echo "set"
esac

これを行うには、以下のような方法があります。

if [ -z "$1" ]

$ 1がnullまたは設定されていない場合、これは成功します


パラメータが設定されていないかであるか( "Null") 、値を設定するかどうかをテストする方法は次のとおりです

+--------------------+----------------------+-----------------+-----------------+
|                    |       parameter      |     parameter   |    parameter    |
|                    |   Set and Not Null   |   Set But Null  |      Unset      |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word}  | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word     | assign word     |
| ${parameter=word}  | substitute parameter | substitute null | assign word     |
| ${parameter:?word} | substitute parameter | error, exit     | error, exit     |
| ${parameter?word}  | substitute parameter | substitute null | error, exit     |
| ${parameter:+word} | substitute word      | substitute null | substitute null |
| ${parameter+word}  | substitute word      | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+

ソース: POSIX:パラメータ拡張

"substitute"と表示されるすべての場合において、式は示された値に置き換えられます。 "assign"で示されるすべてのケースでは、パラメータにはその値が割り当てられ、式も置き換えられます。


私はいつも他の答えでPOSIXテーブルがgrokに遅いことを知っているので、ここにそれを取ります:

   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |          ""           |       "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |          ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |          ""           |       exit 127        |
 + |  ${VARIABLE+default} | "default"  |       "default"       |          ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |       "default"       |       "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} | "default"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

各グループ(コロンの有無にかかわらず)は同じセット未設定のケースを持っているので、異なる点は空のケースの処理方法だけです。

前のコロンでは、 空のケースとセットされていないケースは同一なので、可能な限りそれらのケースを使用します(空のケースに一貫性がないため、 =だけでなく、 :=使用します)。

見出し:

  • setVARIABLEが空でないことを意味します( VARIABLE="something" )。
  • VARIABLEが空/ヌル( VARIABLE="" )であることを意味します。
  • unsetVARIABLEが存在しないことを意味します( unset VARIABLE

値:

  • $VARIABLEは結果が変数の元の値であることを意味します。
  • "default"は、結果が置換文字列であることを意味し"default"
  • ""は結果がnull(空文字列)であることを意味します。
  • exit 127は、スクリプトが終了コード127で実行を停止することを意味します。
  • $(VARIABLE="default")は結果が変数の元の値であり、提供された置換文字列が将来の使用のために変数に代入されることを意味します。

変数がバインドされているかアンバインドされているかをテストしたい場合は、nounsetオプションをオンにしてもうまくいきます:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi

set -uしてスクリプトを実行しているときに、未設定か空であるどうかを調べたい人は、

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

通常の[ -z "$var" ]チェックはvar; unbound variable失敗しvar; unbound variable var; unbound variableが失敗してもset -u var; unbound variable場合set -u [ -z "${var-}" ]を空の文字列にexpandsします。


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

空を含む $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=()、declareを呼び出すと適切な結果が得られます
  • 変数が設定されていないか空の配列の場合にのみ、declareが呼び出されるため、/ dev / nullに渡されるデータは決してありません。

この関数は、次の条件で示されるようにテストします。

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

詳細については

およびテストスクリプトは、私の見るanswerの質問には、「変数がbashで存在する場合、どのようにチェックしますか?」

備考:のanswerでdeclare -pも示されているように、同様の使い方は本当に偶然です。そうでなければ私はもちろんそれを信用しているだろう!answer


私はいつもこのコードを最初に見た人が理解しやすいように、これを使っています:

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

空でないかどうかチェックしたい場合は、

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi

それでおしまい。


if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

引数については、通常は引数の数である$#をテストするのが最善ですが、私の意見では。

if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

これは私が毎日使っているものです:

#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}

これはLinuxとSolarisの下でbash 3.0にうまくいきます。

bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1

未設定の場合は終了したい

これは私のために働いた。 パラメータが設定されていないと、エラーメッセージでスクリプトを終了したかったのです。

#!/usr/bin/env bash

set -o errexit

# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"

これは実行時にエラーを返します

[email protected]:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument

チェックのみ、終了なし - 空と未設定は無効です

値set = VALIDかunset / empty = INVALIDだけをチェックしたい場合は、このオプションを試してください。

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

または、短期間のテストでも;-)

[ "${TSET:-}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"

チェックのみ、終了なし - 空の場合はINVALID

これが質問の答えです。 set / empty = VALIDまたはunset = INVALIDの値だけをチェックする場合は、これを使用します。

注記、 ".. 1}"の "1"は重要ではなく、何でもかまいません(xのように)

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

短いテスト

[ "${TSET+1}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"

私はこの答えを@ mklement0(コメント)に捧げてくれました。

参照先http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02


できるよ:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}

変数に空でない値が設定されているかどうかを確認するには、 [ -n "$x" ]使用します。

ほとんどの場合、設定されていない変数と同じ方法で空の値を持つ変数を扱うことをお勧めします。 しかし、もしあなたが必要ならば、2つを区別することができます: [ -n "${x+set}" ]"${x+set}"がセットさset場合は"${x+set}"展開し、 xsetない場合は空の文字列に展開します。

パラメータが渡されたかどうかを調べるには、関数に渡されるパラメータの数である$#テストします(関数の中にないときはスクリプトに渡します)( Paulの答えを参照)。


[[ $foo ]]

または

(( ${#foo} ))

または

let ${#foo}

または

declare -p foo

あなたが[email protected]何かをチェックしたいなら、これを行うための(もっと)良いコードを見つけました。

if [[ $1 = "" ]]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

なぜこのすべて? [email protected]すべてがBashに存在しますが、デフォルトでは空白なので、 test -ztest -ntest -nと手助けできませんでした。

更新:パラメータ内の文字数をカウントすることもできます。

if [ ${#1} = 0 ]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

最近のバージョンのBash(4.2以降のバージョンでは、わかりません)では、これを試してみましょう:

if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    echo "Variable is unset"
elif [ -z "$SOMEVARIABLE" ]
then
    echo "Variable is set to an empty string"
else
    echo "Variable is set to some string"
fi

bash manページの「Parameter Expansion」セクションを読んでください。 パラメータの拡張は、設定されている変数の一般的なテストを提供しませんが、パラメータが設定されていない場合、パラメータに対して行うことができるいくつかのことがあります。

例えば:

function a {
    first_arg=${1-foo}
    # rest of the function
}

first_argが割り当てられている場合は$1設定され、そうでない場合は "foo"という値が使用されます。 絶対に単一のパラメータを取る必要があり、適切なデフォルトが存在しない場合は、パラメータが与えられていないときにエラーメッセージで終了することができます:

function a {
    : ${1?a must take a single argument}
    # rest of the function
}

(この例では、 $1で何もしたくないので、これを設定しないと終了します)


私はbashの粗雑なディテールを隠すための補助機能が好きです。この場合、そうすることでさらに隠されたクルーデーを加えることができます:

# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

私が最初にこの実装(JensとLionelの答えに触発された)にバグを持っていたので、私は別の解決策を思いつきました:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

私はそれがより簡単で、より忙しくて理解しやすい/覚えやすいと思っています。テストケースはそれが同等であることを示します:

function main()
{
  declare -i xyz
  local foo
  local bar=
  local baz=''

  IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"
  IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"
  IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"
  IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"

  IsDeclared xyz; echo "IsDeclared xyz: $?"
  IsDeclared foo; echo "IsDeclared foo: $?"
  IsDeclared bar; echo "IsDeclared bar: $?"
  IsDeclared baz; echo "IsDeclared baz: $?"
}

main

テストケースでは、varが宣言されてlocal varないことも示されます( '='の後に続く場合を除きます)。かなり長い間、私は変数をこのように宣言したと思っていました。私が単に私の意図を表明したことを発見するには...それはノーオペレーションです。

IsDeclared_Tricky xyz:1
IsDeclared_Tricky foo:1
IsDeclared_Tricky bar:0
IsDeclared_Tricky baz:0
IsDeclared xyz:1
IsDeclared foo:1
IsDeclared bar:0
IsDeclared baz:0

ボナス:ユースケース

私は主にこのテストを使って、幾分「エレガントで」安全な方法で(ほとんどの場合、インターフェイスに似ています...)関数にパラメータを渡します(そして返します):

#auxiliary functions
function die()
{
  echo "Error: $1"; exit 1
}

function assertVariableDeclared()
{
  IsDeclared "$1" || die "variable not declared: $1"
}

function expectVariables()
{
  while (( $# > 0 )); do
    assertVariableDeclared $1; shift
  done
}

# actual example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

必要なすべての変数が宣言された状態で呼び出された場合:

こんにちは世界!

else:

エラー:変数が宣言されていません:outputStr


bash 4.2では、変数の値をテストするのではなく、変数( man bash )が存在するかどうかの実際のテストをサポートしています。

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

変数が設定されているかどうかを知る最も簡単な方法は[[ -z "$var" ]]ですが、 -zオプションは未設定変数と空文字列に設定された変数を区別しません。

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

変数のタイプ(env変数、パラメータ、または通常の変数)に従ってチェックするのが最善です。

env変数の場合:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

パラメータの場合(たとえば、パラメータ$5存在を確認する場合):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

通常の変数(補助関数を使用して、上品な方法で行います):

function declare_var {
   declare -p "$1" &> /dev/null
   return $?
}
declare_var "var_name" && echo "Set" || echo "Unset"

ノート:

  • $#は、位置パラメータの数を示します。
  • declare -pパラメータとして渡される変数の定義を提供します。 存在する場合は0を返し、そうでない場合は1を返し、エラーメッセージを出力します。
  • $? 最後に実行したコマンドのステータスコードを表示します。

シェルでは、文字列の長さがゼロの場合にTrueの-z演算子を使用できます。

設定されていない場合、デフォルトのMY_VARを設定するシンプルな1ライナーです。それ以外の場合はオプションでメッセージを表示できます:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."

(通常)正しい方法

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

${var+x}は、 varが設定されていない場合は何も評価されないパラメータ拡張であり、そうでない場合はxを代入します。

引用漏れ

この構文と使用法は、引用符を必要としないものに展開することを保証しているので(引用符を省略することができます( ${var+x}代わりに"${var+x}"と書くことができます) (つまり、引用符を必要としない単語区切りを含む)か、 [ -z ]結果になり、 [ -z ] [ -z "" ]と同じように同じ値(便宜的に評価されます)になります)。

しかし、引用符は安全に省略することができますが、すぐには分かりませんでした(これはBashの主要なコーダーでもある引用符の説明の最初の著者には明らかではありませんでした)。 O(1)速度ペナルティの可能な限り小さいコストで、 [ -z "${var+x}" ]と引用符を[ -z "${var+x}" ] 。 最初の著者は、この解決策を使用しているコードの隣にこのコメントを追加しました。この答えにURLを付けました。引用符を安全に省略できる理由についての説明も含まれています。

(しばしば)間違った方法

if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi

設定されていない変数と空の文字列に設定された変数を区別しないため、これはしばしば間違っています。 つまり、 var=''ならば、上記の解は "var is blank"を出力します。

unsetと "空文字列に設定"の区別は、ユーザーが拡張子またはプロパティーの追加リストを指定しなければならない状況で必須であり、空白でない値を指定しない場合は空の文字列を指定する必要があります。スクリプトが空の拡張子または追加のプロパティのリストを使用するようにします。

この区別はすべてのシナリオでは必須ではないかもしれません。 それらの場合[ -z "$var" ]はうまくいくでしょう。


私の好みの方法はこれです:

$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set

基本的に、変数が設定されていれば、結果は「結果のfalse 」の否定になりfalsetrue = "set is")。

そして、もしそれが設定されていなければ、それは "結果のtrue否定"(空の結果がtrue評価されるので)になりtrue (したがって、 false = "NOT set"として終了しfalse )。


上記の答えは、Bashオプションset -uが有効な場合は機能しません。 また、それらは動的ではありません。例えば、テストする方法は、 "dummy"という名前で変数が定義されていますか? これを試して:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # Tricky.  Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
    # is defined with this construct: [ ! -z "$var" ].  Instead, we must use default value
    # substitution with this construct: [ ! -z "${var:-}" ].  Normally, a default value follows the
    # operator ':-', but here we leave it blank for empty (null) string.  Finally, we need to
    # substitute the text from $1 as 'var'.  This is not allowed directly in Bash with this
    # construct: [ ! -z "${$1:-}" ].  We need to use indirection with eval operator.
    # Example: $1="var"
    # Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
    # Code  execute: [ ! -z ${var:-} ]
    eval "[ ! -z \${$1:-} ]"
    return $?  # Pedantic.
}

関連項目: Bashでは、変数が "-u"モードで定義されているかどうかをテストする方法





variables