Bash – why is an array variable not considered set if it is assigned `()`

arraybashvariable

bash manual says:

A parameter is an entity that stores values

A variable is a parameter denoted by a name.

A parameter is set if it has been assigned a value.

An array variable is considered set if a subscript has been assigned a value.

Is an array variable a variable and a parameter?

If yes, why is an array variable not considered set if it is assigned ()?

$ ar=()
$ echo ${ar-This is a new value}
This is a new value

Thanks.

Best Answer

In bash, like in ksh, where $var is an array, $var is actually short for ${var[0]}.

So in:

var=([1]=whatever [2]=blah)

${var+set} would not expand to set, and [[ -v var ]] would return false, because $var has no element of indice 0 (note that in bash, like in ksh, but contrary to most other shells and languages, arrays are sparse arrays, or associative arrays with keys limited to positive integers).

In bash (at least since 4.3), when you declare a variable as array with:

typeset -a var

var is initially unset. It's not even set to an empty list. In 4.3, typeset -p var would return an error. In 4.2 and before it would output:

declare -a a='()'

(as if declaring the array assigned an empty list like it does in zsh)

In 4.4, it outputs:

declare -a var

So, since 4.3, an unset (but declared) array is different from an array that is assigned an empty list.

Still, it's difficult programmatically to differentiate between both. But in practice, the distinction is not very useful. Most likely, what you want to know is how many elements are in the array:

((${#array[@]})) || echo array has no element

See zsh, rc, fish and yash for shells with better array designs.

Related Question