Home > Mobile >  How does Bash assign the result of a command substitution to a variable when stdout of that command
How does Bash assign the result of a command substitution to a variable when stdout of that command

Time:03-12

Lets say I have the following two Bash scripts:

# script1

var=$(./script2)
echo "$var"
# script2

echo "x y"

Running ./script1 outputs x y. As noted here, "Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command". When applied to the execution of script1 I understand this as follows: As the standard output of ./script2 is x y the command substitution in script1 has to be replaced such that the corresponding line becomes var=x y. However, running

# script1 - command substitution replaced

var=x y
echo "$var"

would result in the expected error ./script1: line 3: y: command not found. I know that var='x y' would work, but stdout of ./script2 is x y and not 'x y'. So how does Bash do the replacement internally exactly?

CodePudding user response:

how does Bash do the replacement internally exactly?

becomes var=x y

The line is not re-parsed or re-evaled after the substitution. After the substitution, x y is one word, and it stays to be one word, and that one word is assigned to the variable.

Or, said differently, word splitting expansion (which splits one word into multiple words) is not performed on assignment.

The text after the ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable.

When you write x y then these are parsed by the shell as two words. When shell takes the result of an expansion, it stays to be one word, until something splits it into multiple words.

Or a different counterexample:

var=$(echo '"a')

It's not the same as var="a. The line is not re-evaled, the result of command substitution "a is a word, a single token, that is assigned to var.

how does Bash do the replacement internally exactly?

I think start from here https://github.com/bminor/bash/blob/9439ce094c9aa7557a9d53ac7b412a23aa66e36b/subst.c#L3209 .

CodePudding user response:

Section 2.9.1 (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01) describes the sequence of expansions performed on a simple command. Step 4 is "Each variable assignment shall be expanded for tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal prior to assigning the value." Note that "field splitting" is not mentioned here. Basically, the right hand side of a variable assignment is not subject to field splitting.

  • Related