Since you want to see the output from your echo
command, you need to separate the stdout output from the return (exit) code:
#!/bin/bash
func(){
local a=$1 b=$2
echo "$a" # stdout output
echo "$b"
if (( a > b )) # see below for how this could be simplified.
then
return 0 # set exit code
else
return 1
fi
}
c=1 d=4
while ! func $c $d
do
((c++))
done
That way, you're free to use the function directly (prefixed with !
to negate the test's outcome), without a command substitution, and let its return (exit) code drive the outcome of the while
loop condition (an exit code of 0
meaning success, any other meaning failure).
By using just ! func $c $d
as the condition, func
's stdout output is simply printed as is.
Addendum: Billy Wayne McCann's answer points out that there's no strict need to use explicit return
statements to set the exit code (but there's no need to use test
[1]).
(( a > b ))
can be used by itself as the last statement in the function, to set the exit code implicitly:
If there's no explicit return
statement, it is a function's last command that sets its exit code (the same applies analogously to scripts in the absence of an exit
statement).
(( ... ))
sets the exit code to 1
, if ...
evaluates to 0
, and 1
otherwise (any non-negative result). A Boolean expression such as a > b
results in 1
, if the expression is true, and 0
otherwise. Therefore, (( a > b ))
by itself does the same thing implicitly that the above if
statement does explicitly:
func(){
local a=$1 b=$2
echo "$a" # stdout output
echo "$b"
(( a > b )) # exit code implicitly set to 0, if test *succeeds*, 1 otherwise
}
[1] Using test
or [ ... ]
is the POSIX-compliant way to evaluate a condition. Unless your code must be POSIX-compliant, Bash's [[ ... ]]
and (( ... ))
(for arithmetic Boolean tests) are the better choice - see https://stackoverflow.com/a/29320710/45375