初期化されずに設定されていない配列の奇妙な動作

初期化されずに設定されていない配列の奇妙な動作

私はスクリプトを書いていますが、初期化されずに設定されていない配列変数の予期しない動作を見つけましたが、理解できませんでした。

まず長さです。

$ echo ${#notset[@]}
0
$ uninitialized=
$ echo ${#uninitialized[@]}
1

なぜuninitialized長さは1ですか? 0でなければなりませんか?空の変数が空の要素の配列として扱われるからですか?

この事実はいくつかの問題を引き起こします。たとえば、配列を作成し、ユーザーのコマンドラインパラメータに従って一定量のコンテンツを挿入するとします。(+)のようにすれば良いと思います。

myarray=

if [ some-condition ]
then
    myarray[${#myarray[@]}]=some-value
fi

if [ some-condition2 ]
then
    myarray[${#myarray[@]}]=some-value2
elif [ some-condition3 ]
then
    myarray[${myarray[@]}]=some-value3
    myarray[${myarray[@]}]=some-value4
fi

しかし、これを行うと、最初のスロットが空で気に入らず、配列に要素が含まれていることを確認したい場合は、私が書いたいくつかのコード(*)が破損します。どうすればいいですか?

[ -z "${myarray[@]}" ]

配列に複数の要素が含まれているとエラーが発生します。

[ -z "$myarray" ]

配列が空でない場合でも、最初の要素が空であるため失敗します。

それでは、初期化されていない配列をどのように制御する必要がありますか?

処理するときに正確に何が起こっているのか誰かを説明できますか?ソート設定解除 - 初期化されていない変数?


(+)変数を「宣言」しなくても機能できることはわかっていますが、このスクリプトは教授がレビューする予定であり、教授は変数が任意の場所に定義されることを好まない。

(*)この作業をする前は、配列の長さを別の変数に保存しておいたので問題はありませんでした。しかし、私はこの補助変数を定義したくありません。なぜなら、それらなしで長さを得ることができることを知っているからです。

答え1

次の違いを確認できますdeclare -p

unset foo
declare -a foo
declare -p foo
# prints declare -a foo='()'
foo=
declare -p foo
# prints declare -a foo='([0]="")'

空の配列を初期化する場合、最初の出力はdeclare -p配列を宣言する最良の方法の良いヒントです。

declare -a array='()'

(このdeclare -a部分はオプションである可能性があり、単純でもarray=()大丈夫です。)

配列に要素が0個あるかどうかをテストするには、${#array[@]}数値比較を使用してください。拡張操作を試みないでください。test -zほとんどの場合、正しい結果は出ません。

答え2

空の配列を初期化するには、次のようにします。

array=()

配列に値を追加するには、次のようにします。

array+=(value)

関連情報