-1

I am getting a few of these errors in my bash script. I am new to the language. Any pointers?

#!/bin/bash
echo "Calculating the value V for all given values"
inflation=(0 0.03 0.05)
tax_rate=(0 0.28 0.35)
for I in inflation
do
        for R in tax_rate
        do
                V=(4000*((1+0.07*(1-R))/(1+I))^10)
                echo -n "$V "

        done

done

This is my output:

Calculating the value V for all given values ./investment.sh: line 9: syntax error near unexpected token (' ./investment.sh: line 9: V=(4000*((1+0.07*(1-R))/(1+I))^10)' ./investment.sh: line 12: syntax error near unexpected token done' ./investment.sh: line 12: done'

2
  • The error comes from the (( inside the assignment. V=(....) defines V as an array of words, as in V=( x y z ), and the for the parser, an unquoted ( inside the list can't be handled. You could write V=('4000*((1+0.07*(1-R))/(1+I))^10'), which would make V a one-element array holding a string representation of this formula, but then I wonder why you need an array, if it has only one element. You could simply use a scalar: V='4000*((1+0.07*(1-R))/(1+I))^10'. Commented Jun 15, 2020 at 6:39
  • If you really want to do floating point arithmetic in a shell, you could convert your script to zsh, which has float variables. Commented Jun 15, 2020 at 6:42

1 Answer 1

1
  1. always test your code to https://shellcheck.net on errors (you have too much do statements)
  2. bash can't compute floating numbers itself, use [1] instead
  3. to do arithmetic substitution, use $(( ))
  4. to do arithmetic, without arithmetic substitution, use (( )) form
  5. UPPER CASE variables are reserved for system, better use lower case
  6. inflation=(0 0.03 0.05) is an array, you can access it via "${inflation[@]}"
  7. quote variables ! [2]

[1]

bc <<< "scale=2; (4000*((1+0.07*(1-$r))/(1+$i))^10)"

[2] Learn how to quote properly in shell, it's very important :

"Double quote" every literal that contains spaces/metacharacters and every expansion: "$var", "$(command "$var")", "${array[@]}", "a & b". Use 'single quotes' for code or literal $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. See
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words

Command Substitution: "$(cmd "foo bar")" causes the command 'cmd' to be executed with the argument 'foo bar' and "$(..)" will be replaced by the output. See http://mywiki.wooledge.org/BashFAQ/002 and http://mywiki.wooledge.org/CommandSubstitution

$((...)) is an arithmetic substitution. After doing the arithmetic, the whole thing is replaced by the value of the expression. See http://mywiki.wooledge.org/ArithmeticExpression

((...)) is an arithmetic command, which returns an exit status of 0 if the expression is nonzero, or 1 if the expression is zero. Also used as a synonym for "let", if side effects (assignments) are needed.

Finally

#!/bin/bash
  
echo "Calculating the value v for all given values"
inflation=(0 0.03 0.05)
tax_rate=(0 0.28 0.35)
for i in "${inflation[@]}"; do
    for r in "${tax_rate[@]}"; do
        v="$(bc <<< "scale=2; (4000*((1+0.07*(1-$r))/(1+$i))^10)")"
        echo -n "$v "
    done
done
echo

Output

Calculating the value v for all given values
7840.00 6480.00 5920.00 5360.00 4400.00 4000.00 4400.00 4000.00 3600.00
Sign up to request clarification or add additional context in comments.

4 Comments

Instead of $(()), you can also use ((x=a+b)).
Both solutions added
The array access should be double quoted (probably harmless when it contains just numbers, but...)
I'd recommend against using echo -n, since some versions just print "-n" as part of the output (I had an OS update break a bunch of my scripts once...). Use printf '%s ' "$v" instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.