Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have the snippet below in a larger script to basically take my balances out of ledger into two arrays so I can print them the way I want to view them.

#!/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

Every time I try runnning the script I get the error:

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

From my searching, there should be nothing wrong with that line and I just keep coming up empty trying to find a reason why it won't work.

Can anybody point out where I'm wrong?

share|improve this question
1  
Take a look at shellcheck.net –  Cyrus Dec 9 '14 at 20:54

4 Answers 4

up vote 4 down vote accepted

The problem is probably

assets-bal=()

Variable names must not contain a dash. You are limited to underscores.

I don't know how bash interprets assets-bal=() but it considers that an incomplete command which has to be finished on another line. Just run that line in a shell to see what I mean.

share|improve this answer
1  
This line is interpreted as the start of a function declaration. After assets-bal=(), try { echo wibble; } then assets-bal=. Bash allows function names with nonstandard characters like - and =, but it doesn't allow function bodies to be a simple command. –  Gilles Dec 9 '14 at 23:53

Brace expansion does not support variables since it is done before variables are expanded. Use seq instead, if you absolutely must:

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

Or (much more preferable) get the array keys directly:

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

(Also, for i in .., not for $i in ...)


Hauke Laging got the first error. Once you fix that, this will probably be the next error.


And instead of

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

Consider using:

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

The () outside the command substitution converts it into an array.

share|improve this answer
    
@Hauke Very sorry for the typo! –  muru Dec 9 '14 at 21:05
    
Thanks, I'll definitely use both of those. I probably would have caught the $i error, I just hadn't made it that far with the script failing earlier. –  user66330 Dec 9 '14 at 21:06

You have a syntax ERROR : you can't use a - in the name of a variable.

assets-bal

should be replaced by

 assets_bal   

For the loop, you can use a for loop in the C style :

for ((i=0; i<${num}; i++)); do
share|improve this answer
    
You have a typo in variable name –  sputnick Dec 9 '14 at 21:01

I think maybe you're relying a little too heavily on array types there - and variables in general. If I understand what you're doing up there correctly, I suspect this should do much of the same:

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

That could probably be improved upon a great deal by somehow getting a reading of all values for $a above at once in a stream and then arranging it with a scripted editor like sed or similar. In general a shell variable is a pretty awful place to keep information of any value - or of any significant size for that matter. A shell variable should store only enough information to make retrieving actual information from a file more manageable.

Written as a shell function, the above might look like:

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

...and could be called like:

assets

...for your default list, or like...

assets cash checking

...for a different list without every setting a single shell variable value at all.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.