是否在 bash 中declare -a A
创建一个空数组A
,或者只是设置一个属性以防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 variable
在查询 后的元素数量时得到declare
。访问所有元素时我也会遇到该错误。我知道 Bash 的更高版本对此有不同的处理方式。我还是想知道是否declare
真的定义一个变量(为空)。
答案1
这取决于相应的变量是否已经在当前作用域(顶级也称为全局或当前函数)中声明过。
如果尚未在当前作用域中声明它(请注意,在顶级作用域中,该变量可能具有宣布(并通过从环境导入它来分配),然后声明它(在函数作用域中使其成为函数的本地函数),为其分配一个类型,但不初始化它,甚至不初始化为空列表(declare -p a
显示declare -a a
,不像declare -a a=()
您用 ) 声明和/或分配它那样a=()
。
如果它已经在当前作用域中声明(例如,因为它是在全局作用域中从环境中作为标量变量导入的),那么declare -a a
将尝试转变它到一个数组。
如果它以前是标量,那么它就会变成([0]=value-of-the-variable)
数组。如果它已经是一个数组,则保持不变。如果它是关联数组,则会失败并出现cannot convert associative to indexed array
错误。
请注意,这declare a
不会将数组或散列转换为标量。bash
无论如何都无法将哈希/数组转换为标量。您可以使用declare +aA a
强制标量(如果变量以前是当前范围内的散列/数组,则会失败并出现错误)。
在您的情况下,该变量可能尚未在当前作用域中声明,因此它最终被声明但未分配,这解释了为什么尝试在set -u
.
两者之间的区别宣布和分配的/放变量的状态不特定于bash
。在 POSIX 中sh
,您还可以export
创建变量或readonly
不为其赋值。
$ sh -uc 'unset -v var; readonly var; : "$var"'
sh: 1: var: parameter not set
请注意,unset
取消设置和取消声明变量。在 中bash
,mksh
它yash
可以从外部范围恢复变量。
在 中zsh
,除模拟外,如果变量尚未设置或已设置但来自不同类型(标量、数组或关联数组),则sh
using on 变量会声明并将其设置为空值。typeset