Erro ao configurar a variável para o tamanho de um array no bash

1

Eu tenho o snippet abaixo em um script maior para basicamente tirar meus saldos do razão em dois arrays para que eu possa imprimi-los da maneira que eu quiser visualizá-los.

#!/bin/bash
assets=("assets:checking" "assets:google wallet" "assets:savings" "assets:cash")
assets-bal=()

num=${#assets[@]}
for $i in {0..${num}}
do
  read -a tmp <<< 'ledger -f finances balance "${assets[${i}]}"'
  assets-bal[${i}]=tmp[0]
  echo "${assets[${i}]}   ${assets-bal[${i}]}"
done

Toda vez que tento executar o script, recebo o erro:

syntax error near unexpected token 'num=${#assets[@]}'
'num=${#assets[@]}'

Da minha busca, não deve haver nada de errado com essa linha e eu continuo chegando vazia tentando encontrar uma razão pela qual isso não funcionará.

Alguém pode apontar onde estou errado?

    
por user66330 09.12.2014 / 21:50

4 respostas

4

O problema é provavelmente

assets-bal=()

Os nomes das variáveis não devem conter um traço. Você está limitado a sublinhados.

Eu não sei como bash interpreta assets-bal=() , mas considera que um comando incompleto tem que ser terminado em outra linha. Basta executar essa linha em um shell para ver o que quero dizer.

    
por 09.12.2014 / 21:52
2

A expansão do recurso não suporta variáveis, pois é feito antes que as variáveis sejam expandido . Use seq , se você precisar:

for i in $(seq 0 ${num})

Ou (muito mais preferível) obtenha as chaves do array diretamente:

for i in "${!assets[@]}"

(também, for i in .. , não for $i in .. .)

Hauke Laging obteve o primeiro erro. Depois de corrigir isso, esse provavelmente será o próximo erro.

E em vez de

read -a tmp <<< 'ledger -f finances balance "${assets[${i}]}"'

Considere o uso de:

tmp=($(ledger -f finances balance "${assets[${i}]}"))

O () fora da substituição do comando converte-o em uma matriz.

    
por 09.12.2014 / 21:53
1

Você tem uma sintaxe ERRO: não é possível usar - no nome de uma variável.

assets-bal

deve ser substituído por

 assets_bal   

Para o loop, você pode usar um loop for no estilo C:

for ((i=0; i<${num}; i++)); do
    
por 09.12.2014 / 21:57
-1

Acho que talvez você esteja confiando demais nos tipos de array - e variáveis em geral. Se eu entendi o que você está fazendo corretamente, eu suspeito que isso deve fazer o mesmo:

for a in checking google\ wallet savings cash
do  a=assets:$a
    printf "$a\t%d\n" "$(ledger -f finances balance "$a")"
done

Isso provavelmente poderia ser melhorado de alguma forma, obtendo uma leitura de todos os valores de $a acima de uma só vez em um fluxo e organizando-o com um editor de script como sed ou similar. Em geral, uma variável de shell é um lugar muito ruim para manter informações de qualquer valor - ou de qualquer tamanho significativo. Uma variável de shell deve armazenar apenas informações suficientes para tornar a recuperação de informações reais de um arquivo mais gerenciável.

Escrito como uma função de shell, o acima pode parecer com:

assets() if   [ "$#" -gt 0 ]
         then while [ "$#" -gt 0 ]
              do    printf "assets:%s\t%d\n" "$1" "$(
                    ledger -f finances balance "assets:$1")"
              shift;done
         else assets checking google\ wallet savings cash
         fi

... e pode ser chamado assim:

assets

... para sua lista padrão ou como ...

assets cash checking

... para uma lista diferente sem definir um único valor de variável do shell.

    
por 10.12.2014 / 05:34

Tags