
declare -a A
bash で空の配列を作成しますか、それとも後で割り当てられる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 a
、declare -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
こともできます。export
readonly
$ sh -uc 'unset -v var; readonly var; : "$var"'
sh: 1: var: parameter not set
unset
どちらも変数の設定と宣言を解除することに注意してください。ではbash
、外部スコープから変数を復元する場合があります。mksh
yash
では、エミュレーションzsh
の場合を除き、変数に対して を使用すると、その変数がまだ設定されていない場合、または設定されていても異なる型 (スカラー、配列、連想配列) から設定されている場合は、その変数が空の値として宣言され、設定されます。sh
typeset