Eu tenho muitos arrays associativos e quero usar apenas 1 loop. selecione a matriz para loop por um determinado nome
Eu quero selecionar/construir uma parte do arrayname com uma variável e fazer um loop com esse nome, mas não funciona.
Como em OUTPUT3 e OUTPUT4, mas a sintaxe está errada.
Para a saída 3, recebo: "substituição incorreta do bash"
Para a saída 4, recebo: "apenas o arrayname e 0"
#!/bin/bash
clear
declare -A a1 a2 a3
a1['1']="1-1V"
a2['1']="2-1V"
a2['2']="2-2V"
a3['1']="3-1V"
a3['2']="3-2V"
a3['3']="3-3V"
# 1 OUTPUT WORKS
for i in ${!a1[*]}
do
echo -e "$i : ${a1[$i]}"
done
# 2 OUTPUT WORKS
for i in ${!a2[*]}
do
echo -e "$i : ${a2[$i]}"
done
# 3 OUTPUT - WRONG SYNTAX
selectkey="3"
for i in ${!a$selectkey[@]}
do
echo -e "$i : ${a$selectkey[$i]}"
done
# 4 OUTPUT - WRONG SYNTAX
key="3"
aselect="a${key}[*]"
# THIS ECHO WORKS
echo -e "ARRAY: ${!aselect}"
for i in ${!aselect[@]}
do
echo -e "$i : ${aselect[$i]}"
done
ATUALIZAR
A solução é nameref
|declare -n
Isso funciona para mim agora:
#!/bin/bash
clear
declare -A a1 a2 a3
a1['1']="1-1V"
a2['1']="2-1V"
a2['2']="2-2V"
a3['1']="3-1V"
a3['2']="3-2V"
a3['3']="3-3V"
varname="a3"
counter=1
declare -n refname=${varname}
for i in "${!refname[@]}"
do
echo -e "$counter ${refname[$counter]}"
counter=$((counter+1))
done
Use um "nameref":
declare -n a=b
torna a variávela
um alias para a variávelb
.saídas
Matrizes associativas são inerentemente desordenadas.
Para o nº 4, você está usando "expansão indireta" conforme descrito em Shell Parameter Expansion , mas não pode obter os índices da matriz com essa técnica.
bash
não possui arrays multidimensionais. No entanto, você pode implementá-los com uma matriz associativa e concatenação de chave (key1
ekey2
representada como a string combinadakey1,key2
). Aqui estão alguns exemplos.Dado o seu cenário inicial,
Todos
a[1,*]
os valores:Saída
Todos
a[*,2]
os valores:Saída
Uma forma alternativa de produzir o conjunto de chaves:
Saída
Observe que em todos os casos as teclas não estão em ordem numérica. Se isso for necessário, você pode modificar a
printf | awk
construção para canalizarsort -n
(assumindo chaves numéricas).Você também pode generalizar a
awk
construção para poder especificar o número do campo, bem como o valor da chave necessária. Isso ajudaria no encapsulamento, talvez ocultando a geração de chaves em uma funçãoSe seus índices são números, provavelmente é melhor usar arrays regulares em vez de arrays associativos. Ambos podem ser esparsos, mas arrays regulares permitem iterar sobre as chaves em ordem numérica, enquanto para arrays associativos é essencialmente aleatório. (Em outras linguagens, você pode precisar de matrizes associativas para obter uma matriz esparsa.) Compare:
Então, novamente, se seus índices são números e as matrizes não são esparsas, você pode usar matrizes associativas para simular uma matriz bidimensional e iterar sobre os índices com um loop manual.
(É claro que você pode emular uma matriz esparsa aqui definindo os elementos "não existentes" para algum valor especial que você ignoraria dentro do loop.)
Ksh também suporta arrays bidimensionais, ou, pelo menos, listas aninhadas:
embora isso não funcione:
Porém, a necessidade de estruturas de dados complexas também é uma das situações em que pode ser útil considerar a mudança dos shells para alguma outra linguagem de programação.
De qualquer forma, não use
${!array[*]}
, ou${!array[@]}
(com ou sem o!
), mas"${!array[@]}"
sim, pois é o único que mantém intactos os valores que contêm espaços em branco. Tente, por exemploz=("foo bar" "zoom")
, e comparefor x in ${z[*]}; do echo $x; done
com o mesmo usando"${z[*]}"
ou"${z[@]}"
.