配列変数に「()」値が割り当てられていると設定されたと見なされないのはなぜですか?

配列変数に「()」値が割り当てられていると設定されたと見なされないのはなぜですか?

Bashのマニュアルは次のように言います:

パラメータは値を格納するエンティティです。

変数は名前で表されるパラメータです。

パラメータに値が割り当てられている場合は、パラメータが設定されます。

下付き文字が割り当てられている場合、配列変数は設定されたと見なされます。

配列変数は変数ですか、それともパラメータですか?

それでは、割り当て時に配列変数が設定されていると見なされないのはなぜですか()

$ ar=()
$ echo ${ar-This is a new value}
This is a new value

ありがとうございます。

答え1

Inはbashinと同じですksh。ここで$varは配列$varであり、実際にはの略語です${var[0]}

だから:

var=([1]=whatever [2]=blah)

${var+set}に拡張されずset、インデックス0を持つ要素がない[[ -v var ]]ため、falseを返します。 )。$varbashksh

bash(少なくとも4.3以降)では、次のように変数を配列として宣言するとき:

typeset -a var

var最初は設定されていません。空のリストに設定されていませんでした。ではエラー4.3typeset -p var返されます。バージョン4.2以下では、以下を出力します。

declare -a a='()'

(配列を宣言すると空のリストが割り当てられるのと同じですzsh。)

4.4では、出力は次のようになります。

declare -a var

したがって、4.3以降に設定されていない(しかし宣言された)配列は、空のリストが割り当てられた配列と同じではありません。

しかし、プログラム的に2つの違いを区別することは困難です。しかし、実際には、これらの区別はあまり役に立ちません。おそらく、配列にいくつの要素があるかどうかを知りたいでしょう。

((${#array[@]})) || echo array has no element

より良い配列設計を備えたシェルについては、およびzshrc参照fishしてください。yash

答え2

設定されていない場合、構文は${var-foo}次に展開されます。foovarまたは空。空の配列がまさにそれです。

あなたが引用したように:

下付き文字が割り当てられている場合、配列変数は設定されたと見なされます。

お客様のサイトの例()では、下付きar=()文字に値を割り当てません。

答え3

配列全体をテストする正しい方法は次のとおりです。

[[ ${ar[@]+set} == set ]] && echo "array has a value may be a null"

インデックス0の値のテストを作成しています。これら2つは同じです。

${ar+set}
${ar[0]+set}

ただし、どちらも配列全体ではなく、インデックス0の配列が設定されているかどうかをテストします。これがまさにあなたが意味するものだと思います。

しかし、あなたの質問に:割り当て()の場合、配列が設定されていないのはなぜですか?

持っているからいいえnull 以外のすべての値を配列インデックスに割り当てます。
一部のインデックス(および配列)を設定するには、次のものが必要です。

$ declare -a ar=([3]="value")

でも:

$ declare -a ar=([3]="")

zsh(shまたはkshシミュレーションでも)は、テストされたすべてのシェル(通常特殊シェル)のうち、唯一の配列を次のように宣言します。

$ unset ar; typeset -a ar=(); echo $(typeset -p ar) ${ar[@]+set}

コメントの質問:

ありがとうございます。ここで ar[@] を ar[*] に変更できますか?配列変数ですか?

いいえ、anは"${ar[*]}"すべての配列値の文字列連結です。

ただし、この特定の拡張では、「${ar[*]+set}」は同じです。

マニュアルから(配列へ):

下付き文字が@または*の場合、単語はnameのすべてのメンバーに展開されます。

関連情報