Bash – Check variable is an array in Bourne like shell

bashkshshellyashzsh

In Bourne like shell which support array variable, we can use some parsing to check if variable is an array.

All commands below were run after running a=(1 2 3).

zsh:

$ declare -p a
typeset -a a
a=( 1 2 3 )

bash:

$ declare -p a
declare -a a='([0]="1" [1]="2" [2]="3")'

ksh93:

$ typeset -p a
typeset -a a=(1 2 3)

pdksh and its derivative:

$ typeset -p a
set -A a
typeset a[0]=1
typeset a[1]=2
typeset a[2]=3

yash:

$ typeset -p a
a=('1' '2' '3')
typeset a

An example in bash:

if declare -p var 2>/dev/null | grep -q 'declare -a'; then
  echo array variable
fi

This approach is too much work and need to spawn a subshell. Using other shell builtin like =~ in [[ ... ]] do not need a subshell, but is still too complicated.

Is there easier way to accomplish this task?

Best Answer

I don't think you can, and I don't think it actually makes any difference.

unset a
a=x
echo "${a[0]-not array}"

x

That does the same thing in either of ksh93 and bash. It looks like possibly all variables are arrays in those shells, or at least any regular variable which has not been assigned special attributes, but I didn't check much of that.

The bash manual talks about different behaviors for an array versus a string variable when using += assignments, but it afterwards hedges and states that the the array only behaves differently in a compound assignment context.

It also states that a variable is considered an array if any subscript has been assigned a value - and explicitly includes the possibility of a null-string. Above you can see that a regular assignment definitely results in a subscript being assigned - and so I guess everything is an array.

Practically, possibly you can use:

[ 1 = "${a[0]+${#a[@]}}" ] && echo not array

...to clearly pinpoint set variables that have only been assigned a single subscript of value 0.

Related Question