未初始化数组和未设置数组的奇怪行为

Bak*_*riu 7 bash array

我正在编写一个脚本,我发现了一些我不理解的未初始化和未设置数组变量的意外行为。

首先是长度:

$ echo ${#notset[@]}
0
$ uninitialized=
$ echo ${#uninitialized[@]}
1
Run Code Online (Sandbox Code Playgroud)

为什么uninitialized长度是1?不应该是零吗?是因为空变量被认为是一个空元素的数组吗?

这一事实导致了一些问题。例如假设我想创建一个数组,并根据用户命令行参数插入一定数量的东西。我以为我可以做类似(+) 的事情:

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
Run Code Online (Sandbox Code Playgroud)

但这使第一个插槽为空,我不喜欢它,并且还会破坏我编写的一些代码(*),此时假设我想查看数组是否包含任何元素。我该怎么做?

[ -z "${myarray[@]}" ]
Run Code Online (Sandbox Code Playgroud)

如果数组包含多个元素,则引发错误。

[ -z "$myarray" ]
Run Code Online (Sandbox Code Playgroud)

失败,因为第一个元素为空,即使数组不为空。

那么,我应该如何控制数组未初始化?

有人能解释一下在处理数组和未设置 - 未初始化的变量时到底发生了什么吗?


(+)我知道我可以避免“声明”变量并且它会起作用,但是这个脚本将由教授审查,他不喜欢在随机位置定义变量。

(*)在尝试这件事之前,我将数组的长度保存在另一个变量中,所以我没有问题。但是我想避免定义这个辅助变量,因为我知道我可以在没有它们的情况下获得长度。

jw0*_*013 11

你可以看到不同之处declare -p

unset foo
declare -a foo
declare -p foo
# prints declare -a foo='()'
foo=
declare -p foo
# prints declare -a foo='([0]="")'
Run Code Online (Sandbox Code Playgroud)

如果你想初始化一个空数组,第declare -p一个的输出是声明它的最佳方式的一个很好的提示:

declare -a array='()'
Run Code Online (Sandbox Code Playgroud)

(这declare -a部分可能是可选的,一个简单的也array=()应该可以工作。)

如果要测试数组是否有 0 个元素,请在${#array[@]};上使用数值比较。不要尝试test -z在扩展上做一个,因为在很多情况下不会给出正确的结果。


cho*_*oba 8

要初始化一个空数组,请使用

array=()
Run Code Online (Sandbox Code Playgroud)

要将值添加到数组,请使用

array+=(value)
Run Code Online (Sandbox Code Playgroud)