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
%s
tring armazenado no parâmetro posicional$1
st. - 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$IFS
quando for feito e comoset -f
nome 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$var
por sua vez.$(($var=(i+=10)))
é então expandido primeiro para o valor em$var
como$((a=(i+=10)))
e por último de toda a matemática - que primeiro incrementa$i
por 10 e depois atribui o valor de$i
codificar%.
- Cada valor em