web-dev-qa-db-ja.com

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

しますdeclare -a A空の配列Aをbashに作成しますか、それとも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 variabledeclareの後の要素数を照会する場合。また、すべての要素にアクセスするとエラーが発生します。それ以降のバージョンのBashでは、これが異なる方法で処理されることを知っています。それでも、declareが実際にdefines変数(空にする)であるかどうかを知りたいです。

7
U. Windl

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

現在のスコープで宣言されていない場合(そして、最上位のスコープでは、変数にdeclared(および割り当てられている)が環境からインポートされている可能性があります)、宣言します(関数スコープ内にある場合、関数に対してローカルにします)、型を割り当てますが、それを初期化しません。空のリストにもしません(_declare -p a_は_declare -a a_を示しますが、declare -a a=()ではありませんa=())を使用して宣言または割り当てた場合と同じです。

現在のスコープで既に宣言されている場合(たとえば、グローバルスコープのときに環境からスカラー変数としてインポートされたため)、_declare -a a_はconvertを試みます配列。

以前はスカラーだった場合は、_([0]=value-of-the-variable)_配列になります。すでに配列だった場合はそのままにしておきます。連想配列の場合、_cannot convert associative to indexed array_エラーで失敗します。

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

あなたの場合、変数はおそらく現在のスコープでまだ宣言されていなかったため、宣言されたが割り当てられなかったため、_set -u_で展開しようとすると失敗する理由がわかります。

変数の2つのdeclaredassigned/setの状態の違いは、bashに固有のものではありません。 POSIX shでは、変数をexportにするか、値を指定せずにreadonlyにすることもできます。

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

unsetは、変数を設定解除および宣言解除することに注意してください。 bashmkshおよびyashでは、外部スコープから変数を復元できます。

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

14