Returning a value from a bash function

@choroba's answer is correct, however this example might be clearer:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

This example is a little longer (setting $valNumResult then querying that value), but more-explicitly describes what happens: that valNum() returns a value, and that value can be queried and tested.

P.S. Please do yourself a favor and return 0 for true and non-zero for false. That way you can use the return value to indicate "why we failed" in the failure case.


Functions in bash can only return exit codes. The command substitution, conversely, is used to get the standard output of a command or function. Therefore, to check the returned flag, you do not need the substitution:

if valNum "$num" ; then
    # ...
fi

But, for it to work, you should return 0 if the number is valid, and 1 if it is not (exit code 0 means no error).


You cannot return an arbitrary result from a shell function. You can only return a status code which is an integer between 0 and 255. (While you can pass a larger value to return, it is truncated modulo 256.) The value must be 0 to indicate success and a different value to indicate failure; by convention you should stick to error codes between 1 and 125, as higher values have a special meaning (bad external command for 126 and 127, killed by a signal for higher values).

Since you are returning a yes-or-no result here, a status code is appropriate. Since flag seems to indicate a success or failure, you should use the conventional values of 0 for success and 1 for failure (the opposite of what you wrote). You can then use your function directly in an if statement.

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

If you need to discriminate between failure codes, call the function directly. Immediately after it returns, the failure code is available in $?. You can then check it with a case statement:

valNum "$num"
case $? in …

If you need to use the status code later, save it into another variable before $? is overwritten by the next command.

valNum "$num"
valNum_status=$?

What you wrote didn't work because the command substitution $(…) expands to the output of the function, which in your code is either the error message or empty, never 1.

If you need to pass more information than a status code allows out of a shell functions, you have two possibilities:

  • Print some text on standard output, and call the function in a command substitution: $(valNum "$num")
  • Assign to one or more variable inside the function and read those variables later.