2
#!/bin/bash
clear 
echo "Enter a number"
read a 
s = 0
while [ $a -gt 0 ]
do
r = ` expr $a % 10 `
s = ` expr $s + $r `
a = ` expr $a / 10 `
done
echo "sum of digits is = $s"

This is my code guys . I am getting a bunch of expr syntax errors. I am using the bash shell. Thanks!

Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
Robo Smith
  • 21
  • 1
  • 1
  • 2
  • 1
    Take a look at http://www.shellcheck.net/ – Cyrus May 28 '15 at 05:33
  • Funny. `((sum=$(echo $number | sed -e 's/./&+/g' -e 's/$/0/' ) ))` would do about the same, but the performance of @paxdiablo is much better. – Walter A May 28 '15 at 09:07
  • The only use-case for `expr` anymore is for regular expression matching in POSIX shell; any arithmetic it can perform can be done in-shell with `$((...))`, and `bash` has its own (superior) regular expression matching builtin. – chepner May 28 '15 at 13:46

1 Answers1

8

Your error is caused by the spaces surrounding the = in the assignments, the following replacements should work (I prefer $() to using backticks since they're much easier to nest):

s=0
r=$(expr $a % 10)
s=$(expr $s + $r)
a=$(expr $a / 10)

For example, s = 0 (with the spaces) does not set the variable s to zero, rather it tries to run the command s with the two arguments, = and 0.

However, it's not really necessary to call the external expr1 to do mathematical manipulation and capture the output to a variable. That's because bash itself can do this well enough without resorting to output capture (see ARITHMETIC EVALUATION in the bash man page):

#!/bin/bash
clear
read -p "Enter a number: " number
((sum = 0))
while [[ $number -gt 0 ]]; do
    ((sum += number % 10))
    ((number /= 10))
done
echo "Sum of digits is $sum"

You'll notice I've made some other minor changes which I believe enhances the readability, but you could revert back to the your original code if you wish and just use the ((expression)) method rather than expr.


1 If you don't mind calling external executables, there's no need for a loop in bash, you could instead use sneakier methods:

#!/bin/bash
clear
read -p "Enter a number: " number
echo "Sum of digits is $(grep -o . <<<$number | paste -sd+ | bc)"

But, to be brutally honest, I think I prefer the readable solution :-)

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    `(())` is the `let` command and works very differently than expr, a better comparison would be to the builtin `$(())` arithmetic command that comes with bash. `let` allows you to assign variables values but does not return that value so cannot be used with echo or assigned to a variable, unlike both expr and `$(())` which both return/print the value – 123 May 28 '15 at 08:27
  • @User112638726, since all the expressions here are *assignment* expressions, it doesn't actually make any difference in this case. It's something the OP can examine if they ever need to do something more complex but I don't think I need to cover it here. – paxdiablo May 28 '15 at 08:55
  • The way you have worded your answer makes it sound like `let` is a like for like replacement for `expr` and as i explained above it is not. I think it would have been useful to include `$(())` as it does perform exactly the same as expr in regards to arithmetic. – 123 May 28 '15 at 09:04
  • @User112638726, I changed the wording, I don't really want to introduce concepts that aren't needed for the specific case. *Hopefully* the update will address your concerns. If not, there's nothing preventing you from writing another answer to cover that. I'd vote it up since it's still useful. – paxdiablo May 28 '15 at 09:14
  • Okay thanks, and i might do :) It's just sometimes something that seems obvious to you may not be to someone new to the language. I appreciate it though :) – 123 May 28 '15 at 09:20