3

My program is

#!/bin/sh
printf 'Please enter salary amount: '
read salary
TAX="echo $salary * 0.15 | bc"
NET="echo $salary + $TAX | bc"

printf "Net Salary= %.2f" $NET
printf "\n"

But whatever I try I can't get the output I expect. Right now I am getting

$ . 3_net_salary.sh 
Please enter salary amount: 300
-bash: printf: echo: invalid number
-bash: printf: +: invalid number
-bash: printf: echo: invalid number
-bash: printf: 1_simple.awk: invalid number
-bash: printf: 1_simple_awk.sh: invalid number
-bash: printf: 2_simple_awk.sh: invalid number
-bash: printf: 2_simple_before.awk: invalid number
-bash: printf: 3_net_salary.sh: invalid number
-bash: printf: 4_purchase_amounts.sh: invalid number
-bash: printf: alert_spec.rb: invalid number
-bash: printf: awk_passwd.sh: invalid number
-bash: printf: numbers.txt: invalid number
-bash: printf: sed_to_change_should_syntax_to_expect-to: invalid number
-bash: printf: should_to_expect: invalid number
-bash: printf: t1_spec.rb: invalid number
-bash: printf: test001.txt: invalid number
-bash: printf: test_1_spec.rb: invalid number
-bash: printf: test_2_spec.rb: invalid number
-bash: printf: |: invalid number
-bash: printf: bc: invalid number
-bash: printf: |: invalid number
-bash: printf: bc: invalid number
Net Salary= 0.00Net Salary= 300.00Net Salary= 0.00Net Salary= 0.00Net Salary= 300.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.15Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00Net Salary= 0.00
terdon
  • 242,166
  • This doesn't make much sense - bc is an interactive calculator. You don't need to printf back and forth like that - you can just call bc. You can print arbitrary strings to stdout just by enclosing them in double-quotes - and bc will read an infile with your bc script then to/from the terminal interactively if you wish. – mikeserv Dec 01 '14 at 16:59

1 Answers1

9

You are not doing what you think you're doing. This command:

TAX="echo $salary * 0.15 | bc"

Does not run anything, there is no calculation. That assigns a string to the variable $TAX. Then, because you're not quoting the variable when you pass it to printf, the * will expand to everything in the current directory. To illustrate:

$ ls
file1  file2
foo="echo 12 * 4 | bc"
$ echo $foo
echo 12 file1 file2 4 | bc

As you can see above, the * expanded to the contents of the directory and no calculation was made. In order to assign the result of a command to a variable, you should use var=$(command), not quotes.

So, a working version of your script would be:

#!/bin/sh
printf 'Please enter salary amount: '
read salary
TAX=$(printf '%s * %s\n' "$salary" "0.15" | bc)
NET=$(printf '%s + %s\n' "$salary" "$TAX" | bc)

printf "Net Salary= %.2f\n" $NET

When debugging something you should always think of printing your variables to understand what they contain.

terdon
  • 242,166
  • There is no need for the unreadable printf '%s * %s\n' "$salary" "0.15" . One can use echo "0.15 * $salary". the "-quotes suppress the filename globbing but allows the evaluation of variables. – miracle173 Dec 01 '14 at 07:53
  • 1
    @miracle173 readibility is in the eye of the beholder I guess. However, there are very real reasons to prefer printf even if you might find it less readable. – terdon Dec 01 '14 at 12:40