The function "printf -v" inside does not work with redirected output

With bash 4.1.2 and 4.3.48, the following script gives the expected result:

#!/bin/bash returnSimple() { local __resultvar=$1 printf -v "$__resultvar" '%s' "ERROR" echo "Hello World" } returnSimple theResult echo ${theResult} echo Done. 

Conclusion of the expected result:

 $ ./returnSimple Hello World ERROR Done. 

However, when stdout is passed from a function to another process, assigning the __resultvar variable no longer works:

 #!/bin/bash returnSimple() { local __resultvar=$1 printf -v "$__resultvar" '%s' "ERROR" echo "Hello World" } returnSimple theResult | cat echo ${theResult} echo Done. 

Unexpected conclusion:

 $ ./returnSimple Hello World Done. 

Why printf -v does not work in the second case? Should printf -v not write the value to the result variable regardless of whether the output of the function is passed to another process?

+8
linux unix bash
source share
2 answers

See man bash , Pipelines section:

Each command in the pipeline is executed as a separate process (i.e., in a subshell).

Therefore, when you write cmd | cat cmd | cat , cmd gets a copy of the variable that it cannot change.

Simple demo:

 $ test() ((a++)) $ echo $a $ test $ echo $a 1 $ test | cat $ echo $a 1 
+8
source share

Interestingly, the same thing happens when using eval $__resultvar="'ERROR'" instead of the printf -v operator. So this is not a printf related issue.

Instead, adding echo $BASH_SUBSHELL to the main script, and the function shows that the shell generates a subcolumn in the second case - since it needs to pass the output from the function to another process. Therefore, the function works in a subclass:

 #!/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 why any variable assignments from a function are not passed back to the calling script.

+2
source share

All Articles