With bash 4.1.2 and 4.3.48, the following script gives the expected output:
#!/bin/bash
returnSimple() {
local __resultvar=$1
printf -v "$__resultvar" '%s' "ERROR"
echo "Hello World"
}
returnSimple theResult
echo ${theResult}
echo Done.
Output as expected:
$ ./returnSimple
Hello World
ERROR
Done.
However, when stdout from the function is piped to another process, the assignment of the __resultvar
variable does not work anymore:
#!/bin/bash
returnSimple() {
local __resultvar=$1
printf -v "$__resultvar" '%s' "ERROR"
echo "Hello World"
}
returnSimple theResult | cat
echo ${theResult}
echo Done.
Unexpected Output:
$ ./returnSimple
Hello World
Done.
Why does printf -v
not work in the second case? Should printf -v
not write the value into the result variable independent of whether the output of the function is piped to another process?
See man bash
, section on Pipelines
:
Each command in a pipeline is executed as a separate process (i.e., in a subshell).
That's why when you write cmd | cat
, cmd
receives a copy of variable that it can't modify.
A simple demo:
$ test() ((a++))
$ echo $a
$ test
$ echo $a
1
$ test | cat
$ echo $a
1
Interestingly enough, the same also happens when using eval $__resultvar="'ERROR'"
instead of the printf -v
statement. Thus, this is not a printf
related issue.
Instead, adding a echo $BASH_SUBSHELL
to both the main script and the function shows that the shell spawns a sub shell in the second case - since it needs to pipe the output from the function to another process. Hence the function runs in a sub shell:
#!/bin/bash
returnSimple() {
local __resultvar=$1
echo "Sub shell level: $BASH_SUBSHELL"
printf -v "$__resultvar" '%s' "ERROR"
}
echo "Sub shell level: $BASH_SUBSHELL"
returnSimple theResult | cat
echo ${theResult}
echo Done.
Output:
% ./returnSimple.sh
Sub shell level: 0
Sub shell level: 1
Done.
This is the reason why any variable assignments from within the function are not passed back to the calling script.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With