Encontre o número de elementos na matriz referenciados por um nome criado dinamicamente

Encontre o número de elementos na matriz referenciados por um nome criado dinamicamente

Encontrei uma pergunta semelhanteaqui, mas não parece ser idêntico e nenhuma das respostas fornece a saída que desejo. Eu tenho uma matriz para a qual desejo descobrir quantos elementos ela contém, acessando-a usando um nome gerado dinamicamente.

declare -a array0=(2 4 2 5)  # contains 4 values
indx=0
Name="array$indx"            # create a name reference => array0

# I know how to obtain an indexed value by INDIRECT reference:
val0=${!Name[0]}
# I also know how to get array length using DIRECT name
len=${#array0[@]}

O que eu preciso é encontrar o número de elementos domatriz0referenciando-o usando a variávelNome

len=${#!Name[@]}             # the syntax is incorrect

Alguma sugestão para implementação?

EDITAR:
Eu estava errado sobre poder acessar as entradas da matriz usando isto:

val0=${!Name[0]}

Funciona apenas para indx=0, então se eu quiser obter outras entradas do array, ele simplesmente retornará uma string vazia:

val4=${!Name[4]}          #does not work

ou

i=4
val4=${!Name[$i]}         # does not work

Responder1

Com bash-4.3ou superior, você pode usar namerefs:

a0=(a b c)
i=0
typeset -n Name="a$i"
echo "${#Name[@]}"

ou você sempre podeusareval. De qualquer forma, não se engane pensando que usar bashnamerefs émais seguraque eval. Assim como for eval, você ainda precisa ter certeza de que o conteúdo de $Nameé um nome de variável de shell válido. Valores como x[`evil-command>&2`0]ainda fariam com que isso evil-commandfosse executado quando você expandisse $Nameou ${#Name}. O mesmo se aplica a ${!var}.

Com ksh93, você poderia usar matrizes multidimensionais:

a[0]=(a b c)
i=0
echo "${#a[i][@]}"

zshtem formas mais consistentes de combinar seus operadores de expansão:

a0=(a b c)
i=0
name=a$i
echo ${(P)#name}

( Ppara expansão indireta de parâmetros).

Responder2

Você pode usar evalexplicitamente, mas não abuse:

eval "len=\${#$Name[@]}"

informação relacionada