bash手册说:
参数是存储值的实体
变量是由名称表示的参数。
如果参数已被赋值,则该参数被设置。
如果下标已被赋值,则数组变量被视为已设置。
数组变量是变量还是参数?
如果是,为什么数组变量在分配时不被视为设置()
?
$ ar=()
$ echo ${ar-This is a new value}
This is a new value
谢谢。
答案1
Inbash
与 in 一样ksh
,其中$var
是一个数组,$var
实际上是 的缩写${var[0]}
。
所以在:
var=([1]=whatever [2]=blah)
${var+set}
不会扩展为set
,并且[[ -v var ]]
会返回 false,因为$var
没有索引为 0 的元素(请注意,在 中bash
,与 in 类似ksh
,但与大多数其他 shell 和语言相反,数组是稀疏数组,或者键仅限于正整数的关联数组)。
在bash
(至少从 4.3 开始)中,当您使用以下命令将变量声明为数组时:
typeset -a var
var
最初未设置。它甚至没有设置为空列表。在 中4.3
,typeset -p var
将返回错误。在 4.2 及之前版本中,它会输出:
declare -a a='()'
(就像声明数组分配了一个空列表一样,就像在 中一样zsh
)
在4.4中,输出:
declare -a var
因此,从 4.3 开始,未设置(但已声明)的数组与分配了空列表的数组不同。
尽管如此,还是很难通过编程来区分两者。但在实践中,这种区别并不是很有用。最有可能的是,您想知道数组中有多少个元素:
((${#array[@]})) || echo array has no element
请参阅zsh
、rc
、fish
和yash
了解具有更好阵列设计的 shell。
答案2
如果未设置,该构造${var-foo}
将扩展为foo
var
或为空。空数组就是这样。
正如你引用的:
如果下标已被赋值,则数组变量被视为已设置。
您站点 ( ) 的示例ar=()
未向任何下标分配值。
答案3
测试整个数组的正确方法是:
[[ ${ar[@]+set} == set ]] && echo "array has a value may be a null"
您编写的是对索引 0 处的值的测试。这两个是等效的:
${ar+set}
${ar[0]+set}
但两者都只会测试索引零处的数组是否已设置,而不是整个数组,我认为这就是您的意思。
但是,对于你的问题:如果分配(),为什么数组未设置?
因为你有不是为任何数组索引分配任何值,甚至不包括 null。
要设置一些索引(以及数组),您需要类似以下内容:
$ declare -a ar=([3]="value")
甚至:
$ declare -a ar=([3]="")
zsh(即使在 sh 或 ksh 模拟中)是所有测试的 shell 中唯一一个(像往常一样,特殊的 shell)将数组声明为:
$ unset ar; typeset -a ar=(); echo $(typeset -p ar) ${ar[@]+set}
评论中的问题:
谢谢。这里的ar[@]可以换成ar[*]吗?它们是数组变量吗?
不,an"${ar[*]}"
是所有数组值的字符串串联。
然而,在这个特定的扩展中:“${ar[*]+set}”两者是等价的。
从手册(在数组):
如果下标是@或*,则该词将扩展到name的所有成员。