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

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

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

首先是长度:

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

为什么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

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

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

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

[ -z "$myarray" ]

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

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

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


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

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

答案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)

相关内容