Atribui identificador variável em loop e ecoa seu valor

2

Espero que esta pergunta não seja duplicada, pois tenho tentado várias maneiras de resolver esse problema, mas não encontrei nenhuma solução.

Eu tenho um loop for no qual gostaria de armazenar uma saída de comando em uma variável cujo nome está mudando a cada rodada e gostaria de fazer echo e fazer outras operações nessas variáveis, algo assim:

for i in 'seq 1 $netsize'
do
    echo "node$i: "
    export Bal$i=$(node$i getbalance | bc)  #PIPE TO BC SINCE getbalance RETURNS FLOAT TYPE VALUE
    echo $Bal$i | tee -a <text-file path>   #THIS GIVES ME ONLY 1,2,... NOT THE getbalance VALUE!!!
...

Além disso, gostaria de pegar o resultado do node1 e dividi-lo pela soma do saldo total de todos os nós. Então eu fiz isso, mas recebo um erro de sintaxe:

...
echo "$Bal1/($Bal1+$Bal2+$Bal3+$Bal4+$Bal5+$Bal6+$Bal7+$Bal8+$Bal9)" | bc >> <text-file path> #HERE; I DO THIS FOR A netsize OF 9 NODES ...

Como eu poderia resolver este segundo problema para um netsize arbitrário?

    
por Aliakbar Ahmadi 07.07.2015 / 14:24

2 respostas

0

Você pode fazer isso com uma matriz bash. Eu salvaria os valores em uma matriz de índice com algo como:

declare -a bal
for i in 'seq 1 $netsize'
do
    echo "node$i: "
    bal[$i]=$(node$i getbalance | bc) //PIPE TO BC SINCE getbalance RETURNS FLOAT TYPE VALUE

    echo ${bal[$i]} # should be the right value
done

em seguida, para reunir o comando que você deseja fazer eco para bc , vamos jogar um pequeno jogo com um subshell e IFS como

denominator=$(IFS=+; echo "${bal[*]:2}")
equation="${bal[1]}/($denominator)"

A configuração de IFS=+ fará com que os campos na matriz sejam separados por + quando os ecoarmos na próxima instrução. O ${bal[*]:2} acessa todos os elementos da matriz bal (essa é a parte ${bal[*]} ). Neste caso, porém, sabemos que o elemento número 1 é algo que queremos pular, já que vamos usar isso no numerador da equação, então adicionamos :2 para obter do índice 2 on. Então, ${bal[*]:2} nos dá todos os elementos da matriz bal index 2 e acima.

Você pode ver mais sobre o bash array slicing nestas respostas ou mais aqui

    
por 07.07.2015 / 15:17
0
netsize=$somenum
(   echo  scale=\(2;  set --                           ### set scale; clear args
    while [ "$#" -lt "$netsize" ]                      ### counts up to $netsize
    do    set "$@" "bal$(($#+1))"                      ### saves arg count as bal$#+1
    ###   I do the below because you don't say what 
    ###   node$# getbalance does. Here it's random.
          eval "node$#(){ "':& x=${!%??} y=${!#"$x"}
                               echo "$x.$y/'"$#\"; }"  ### fakes a node$#() function
          printf "%bbal$#=%b" ');"' '";' \(            ### );"bal$#=";(bal$#=
          "node$#" getbalance                          ### $x.$y/$#\n
    done; printf %b+ ");($1/($@))\c"                   ### );(bal1/(bal1+...bal$netsize))
) | paste -sd\0 | bc                                  ### removes all \newlines but last

Portanto, não é nada fácil dizer o que você está tentando fazer, mas uma coisa que eu notei é que você acha que precisa chamar um bc separado para cada avaliação aritmética. O oposto é de longe a maneira mais conveniente de ir - bc é um programa interativo, além de ser uma linguagem de script completa. Ele irá definir e armazenar os valores das variáveis durante o tempo de atividade - e assim, em vez de tentar armazenar todas essas informações no shell, apenas distribua suas equações e deixe bc armazenar seus valores para você.

Por exemplo:

{ echo 'x=1+2'; echo '"x=";x'; }| bc

... que imprime ...

x=3

Como o primeiro bc avalia x para igual a 1+2 , ele imprime a string arbitrária "x=" para stdout e, por último, é solicitado que ele imprima o valor de x , e assim é. / p>

O script acima faz praticamente a mesma coisa. Para cada iteração, bal é incrementado em um. E imprime para bc :

);"bal$#=";(bal$#=$!/$#\n

... e quando tiver incrementado $# para corresponder a $netsize que imprime (dado um exemplo $netsize of 10) ...

(bal1/(bal1+bal2+bal3+bal4+bal5+bal6+bal7+bal8+bal9+bal10))

Nenhum desses valores é salvo no shell - bc se lembra de todos eles, no entanto. E quando você coloca uma expressão bc em ( parens ) , ela é avaliada e impressa.

Eu uso paste -sd\0 para remover todos os \n ewlines porque não sei o que "node$#" getbalance deve fazer, mas suponho que ele seguirá sua saída com um \n ewline e (bal1= node$# getbalance's output \n) é um erro de sintaxe. Então eu limpo todos eles e separo as expressões com ; semicolons em vez disso (o que eu espero que não seja um caractere node$# getbalance será impresso) . Para ter uma ideia clara do que todo o script imprime, você pode substituir o bc na cauda com tr \; \n .

Aqui, por exemplo, é o que será impresso se netsize=10 :

scale=(2)
"bal1="
(bal1=261.40/1)
"bal2="
(bal2=261.41/2)
"bal3="
(bal3=261.42/3)
"bal4="
(bal4=261.44/4)
"bal5="
(bal5=261.45/5)
"bal6="
(bal6=261.46/6)
"bal7="
(bal7=261.48/7)
"bal8="
(bal8=261.49/8)
"bal9="
(bal9=261.52/9)
"bal10="
(bal10=261.54/10)
(bal1/(bal1+bal2+bal3+bal4+bal5+bal6+bal7+bal8+bal9+bal10))

Tudo isso é executado em bc , que imprime algo como:

bal1=261.40
bal2=130.70
bal3=87.14
bal4=65.36
bal5=52.29
bal6=43.57
bal7=37.35
bal8=32.68
bal9=29.05
bal10=26.15
.34

Se você puder ser mais claro sobre suas entradas e saídas, posso ajudar a adaptar isso especificamente às suas necessidades, mas fazer var=$(echo stuff at | bc) uma vez por iteração é um desperdício.

    
por 08.07.2015 / 08:03