[linux] In bash, how to store a return value in a variable?

The answer above suggests changing the function to echo data rather than return it so that it can be captured.

For a function or program that you can't modify where the return value needs to be saved to a variable (like test/[, which returns a 0/1 success value), echo $? within the command substitution:

# Test if we're remote.
isRemote="$(test -z "$REMOTE_ADDR"; echo $?)"
# Or:
isRemote="$([ -z "$REMOTE_ADDR" ]; echo $?)"

# Additionally you may want to reverse the 0 (success) / 1 (error) values
# for your own sanity, using arithmetic expansion:
remoteAddrIsEmpty="$([ -z "$REMOTE_ADDR" ]; echo $((1-$?)))"

E.g.

$ echo $REMOTE_ADDR

$ test -z "$REMOTE_ADDR"; echo $?
0
$ REMOTE_ADDR=127.0.0.1
$ test -z "$REMOTE_ADDR"; echo $?
1
$ retval="$(test -z "$REMOTE_ADDR"; echo $?)"; echo $retval
1
$ unset REMOTE_ADDR
$ retval="$(test -z "$REMOTE_ADDR"; echo $?)"; echo $retval
0

For a program which prints data but also has a return value to be saved, the return value would be captured separately from the output:

# Two different files, 1 and 2.
$ cat 1
1
$ cat 2
2
$ diffs="$(cmp 1 2)"
$ haveDiffs=$?
$ echo "Have differences? [$haveDiffs] Diffs: [$diffs]"
Have differences? [1] Diffs: [1 2 differ: char 1, line 1]
$ diffs="$(cmp 1 1)"
$ haveDiffs=$?
$ echo "Have differences? [$haveDiffs] Diffs: [$diffs]"
Have differences? [0] Diffs: []

# Or again, if you just want a success variable, reverse with arithmetic expansion:
$ cmp -s 1 2; filesAreIdentical=$((1-$?))
$ echo $filesAreIdentical
0