3

I'm writing a divides-by-three function in Bash, and it won't let me set a variable to a number.

fizzy.sh:

#!/usr/bin/env sh

div3() {
    return `$1 % 3 -eq 0`
}

d=div3 1
echo $d

Example:

$ ./fizzy.sh 
./fizzy.sh: line 7: 1: command not found
mcandre
  • 22,868
  • 20
  • 88
  • 147
  • Your `div3` function does not do what you think it does. – Matt Ball Nov 03 '11 at 21:33
  • 1
    Just for the record / google searchers ==> This isn't the case here, but you get the exact same error if you accidentally add in spaces around the equal sign, `d = div3 1` vs the correct `d=div3 1`. – Peter Ajtai Apr 26 '12 at 19:37

3 Answers3

4

Bash functions normally "return" values by printing them to standard output, where the caller can capture them using

`func args ...`

or

$(func args ...)

This makes functions work like external commands.

The return statement, on the other hand, sets the value of $?. Normally that's going to be set to 0 for success, 1 for failure, or some other value for a specified kind of failure. Think of it as a status code, not a general value. It's likely that this will only support values from 0 to 255.

Try this instead:

#!/bin/sh

div3() {
    expr $1 % 3 = 0   # prints "0" or "1"
}

d=$(div3 1)
echo $d

Note that I've also changed the shebang line from #!/usr/bin/env sh to #!/bin/sh. The #!/usr/bin/env trick is often used when invoking an interpreter (such as perl) that you want to locate via $PATH. But in this case, sh will always be in /bin/sh (the system would break in various ways if it weren't). The only reason to write #!/usr/bin/env sh would be if you wanted to use whatever sh command happens to appear first in your $PATH rather than the standard one. Even in that case you're probably better of specifying the path to sh directly.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
2

The

 d=div3 1

line is the culprit because you assign the string div3 to the env variable d and try to execute 1. To avoid this, use backticks to assign the result of the evaluation instead:

 d=`div3 1`

Then, another error occurs in your evaluation function. You need to run test on your arguments instead of trying to evaluate them as a command:

return `test $(($1 % 3)) -eq 0`

Still no output, but no errors either. What would your expected output be, actually?

thiton
  • 35,651
  • 4
  • 70
  • 100
1
div3() {
    return $(( ( $1 % 3 ) == 0 ))
}

d=$(div3 1)
rc=$?

echo $d
echo $rc


(blank line)
0

Note, return just sets the value of $? for the function to return value, just print it.

div3() {
    printf $(( ( $1 % 3 ) == 0 )) "\n"
}
shellter
  • 36,525
  • 7
  • 83
  • 90