`declare -a A` は Bash で空の配列 `A` を作成しますか?

`declare -a A` は Bash で空の配列 `A` を作成しますか?

declare -a Abash で空の配列を作成しますか、それとも後で割り当てられるA場合に備えて属性を設定するだけですか?A

次のコードを考えてみましょう:

set -u
declare -a A
echo ${#A[*]}
echo ${A[*]}
A=()
echo ${#A[*]}
echo ${A[*]}
A=(1 2)
echo ${#A[*]}
echo ${A[*]}

期待される出力は何でしょうか?

Bash 4.3.48(1)では、bash: A: unbound variableの後の要素の数を照会するとが表示されますdeclare。また、すべての要素にアクセスすると、同じエラーが発生します。Bashのそれ以降のバージョンでは、この処理が異なることは知っています。それでも、declare実際に定義する変数(空になる)。

答え1

それは、対応する変数が現在のスコープ(トップレベル、つまりグローバルまたは現在の関数)で既に宣言されているかどうかによって異なります。

現在のスコープで宣言されていない場合(トップレベルのスコープでは、変数が宣言した(そして環境からインポートして割り当てられます)、それを宣言し(関数スコープ内にある場合は関数に対してローカルにします)、型を割り当てますが、初期化は行わず、空のリストにも割り当てません(declare -p aが表示されdeclare -a adeclare -a a=()を使用して宣言および/または割り当てた場合とは異なりますa=())。

もしそれが現在のスコープで既に宣言されていたら(例えば、グローバルスコープで環境からスカラー変数としてインポートされたため)declare -a a変換するそれを配列に追加します。

以前スカラーだった場合は、([0]=value-of-the-variable)配列になります。すでに配列だった場合は、そのまま残されます。連想配列だった場合は、cannot convert associative to indexed arrayエラーが発生して失敗します。

declare aは配列またはハッシュをスカラーに変換しないことに注意してくださいbash。 はハッシュ/配列をスカラーに変換できません。 を使用するとdeclare +aA aスカラーを強制できます (変数が現在のスコープ内で以前にハッシュ/配列であった場合はエラーで失敗します)。

あなたの場合、変数はおそらく現在のスコープでまだ宣言されていなかったため、宣言されたが割り当てられず、それが で拡張しようとすると失敗する理由を説明していますset -u

2つの違い宣言したそして割り当てられた/セット変数の状態は に固有のものではありませんbash。 POSIX では、変数を作成したり、値を与えずに変数を作成したりするshこともできます。exportreadonly

$ sh -uc 'unset -v var; readonly var; : "$var"'
sh: 1: var: parameter not set

unsetどちらも変数の設定と宣言を解除することに注意してください。ではbash、外部スコープから変数を復元する場合があります。mkshyash

では、エミュレーションzshの場合を除き、変数に対して を使用すると、その変数がまだ設定されていない場合、または設定されていても異なる型 (スカラー、配列、連想配列) から設定されている場合は、その変数が空の値として宣言され、設定されます。shtypeset

関連情報