Return Text from a Function in POSIX sh
A POSIX sh function returns text by printing it, and the caller captures the output with command substitution. Variables set inside are lost, and trailing newlines go.
A function in a POSIX script has to hand back a string, and sh has no return values other than a small exit status.
greet() { printf 'hello %s\n' "$1"; }
msg=$(greet world)
echo "got: $msg"
setit() { x=changed; echo done; }
x=orig
r=$(setit)
echo "r=$r x=$x"
t=$(printf 'a\n\n\n')
echo "[$t]"got: hello world
r=done x=orig
[a]return carries only a number from 0 to 255, so the function prints its result and the caller captures it with $(...). The run in dash shows the two costs. Command substitution runs in a subshell, so x=changed inside setit never reached the caller, and the shell removes every trailing newline from the captured text. Both rules are in the specification of command substitution.
Each call forks a subshell, which adds up in a loop that runs thousands of times. If the function must change variables, assign to a global name such as RESULT and read it afterward. Bash adds printf -v to avoid the fork, but that is not POSIX.