Então, vou definir uma função de impressão indireta primeiro ...
_print() while [ "$#" -ne 0 ]
do printf '$%s = %d\n' \
"$1" "$(($1))"
shift
done
Em seguida, configurarei a matriz e incrementarei ...
arr=( a b c d e ); i=0
for var in "${arr[@]}"
do : "$(($var=(i+=10)))"
done
Agora, o valor de $a é 10 e $b 20 e assim por diante. Por último resta apenas para imprimir ...
_print "${arr[@]}"
... que imprime para stdout ...
$a = 10
$b = 20
$c = 30
$d = 40
$e = 50
Tudo isso funciona devido à maneira como o shell lida com $(( math )) expansões - elas são basicamente eval s. Em uma expansão aritmética, o shell primeiro expande qualquer outra expansão de shell válida antes de tentar fazer as contas - tornando a matemática real sua última ordem de negócios.
Isso significa que, se você fizer isso:
i=a a=10; echo "$(($i))"
O resultado impresso é 10 porque o shell expande o valor de $i para obter a e, em seguida, avalia esse resultado como uma referência inteira.
O acima funcionará em qualquer shell compatível com POSIX.
Isso significa que eu poderia também ter feito ...
i=10
for var in a b c d e
do arr[($var=i*${#arr[@]}+i)/i]=$var
done
... para manipular atribuição de matriz, avaliação de índice e $var integer assignation de uma vez porque os colchetes [ index ] de uma matriz shell denominada - em um shell que os suporta - são tratados de maneira idêntica à $(( expansion )) parens de uma expressão matemática.
A execução do código acima, agrupado em ksh -xc , imprime a seguinte saída de depuração para o erro padrão:
+ arr[1]=a
+ arr[2]=b
+ arr[3]=c
+ arr[4]=d
+ arr[5]=e
De lá, posso fazer apenas:
echo "$((${arr[1]}))"
echo "$((a))"
... para imprimir ...
10
10
... porque eles avaliam a mesma coisa em shells que suportam matrizes nomeadas. No entanto, em conchas que não ...
echo 'arr=(a b c d e)' | bash -x
+ arr=(a b c d e) #bash traces the successful command to stderr
echo 'arr=(a b c d e)' | sh -x
sh: 1: Syntax error: "(" unexpected #sh traces something else
Portanto, na função _print() eu apenas shift sobre os parâmetros posicionais (que representa um array "$@" do shell verdadeiramente portátil) enquanto houver algum e printf . .
- Primeiro, um sinal de cifrão
$. - Em seguida, o valor
%string armazenado no parâmetro posicional$1st. - Em seguida, um sinal de
=é igual. - E por último o valor armazenado no valor armazenado no meu parâmetro posicional
$(($1)).
Como a função shift s seus argumentos desaparecem, o primeiro parâmetro posicional é constantemente substituído pelo próximo até que a contagem $# de posicionais seja igual a 0 e a função retorne.
Antes de executar a função quando inicializo a matriz e suas variáveis indiretas constituintes que funcionam assim:
-
for var in "${arr[@]}"- O shell expandirá
[@]para uma lista de argumentos e[*]para uma única concatenação dessa lista. Se a expansão não for citada, poderá também expandir[*]para uma lista - dependendo se há ou não um valor para$IFSquando for feito e comoset -fnome a expansão está atualmente configurada - mas se o fizer, provavelmente não o faz da maneira que pretende.
- O shell expandirá
-
: "$(($var=(i+=10)))"- Cada valor em
${arr[@]}é atribuído ao valor de$varpor sua vez.$(($var=(i+=10)))é então expandido primeiro para o valor em$varcomo$((a=(i+=10)))e por último de toda a matemática - que primeiro incrementa$ipor 10 e depois atribui o valor de$icodificar%.
- Cada valor em