Localiza o número de elementos na matriz que é referenciada por um nome criado dinamicamente

3

Encontrei uma pergunta semelhante aqui , mas não parece ser idêntico, e nenhuma das respostas fornece a saída que desejo. Eu tenho um array, para o qual eu quero encontrar quantos elementos ele contém, acessando-o usando o 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 do array0 referenciando-o usando a variável Nome

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

Alguma sugestão para implementação?

EDITAR:
Eu estava errado sobre ser capaz de acessar as entradas da matriz usando isso:

val0=${!Name[0]}

Ele só funciona para indx = 0, então, se eu quiser obter outras entradas da matriz, ele simplesmente retorna uma string vazia:

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

ou

i=4
val4=${!Name[$i]}         # does not work
    
por Nazar 31.05.2017 / 22:12

2 respostas

2

Você pode usar eval explicitamente, mas não use em excesso:

eval "len=\${#$Name[@]}"
    
por 31.05.2017 / 22:30
4

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

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

ou você sempre pode usar eval . Em qualquer caso, não se engane pensando que usar bash namerefs é mais seguro que eval . Assim como para eval , você ainda precisa garantir que o conteúdo de $Name seja um nome de variável de shell válido. Valores como x['evil-command>&2'0] ainda causariam a execução de evil-command quando você expandir $Name ou ${#Name} . O mesmo se aplica a ${!var} .

Com ksh93 , você pode usar matrizes multidimensionais:

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

zsh tem formas mais consistentes de combinar seus operadores de expansão:

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

( P para expansão indireta de parâmetros).

    
por 31.05.2017 / 23:36