Wednesday, February 2, 2022

[SOLVED] Why do these different echo commands all print the same thing despite different types of quoting?

Issue

S=2

echo $S
echo "$S"
bash -c " echo $S "
bash -c " echo '$S' "
bash -c " echo "$S" "

Why do all of these echo the same thing? They all print 2 and I don't understand why.

The most confusing one for me is bash -c " echo '$S' ", since echo '$S' = $S. How come bash -c " echo '$S' " works like the others?


Solution

bash -c " echo '$S' "

Because the string " echo '$S' " is double quoted it is being interpolated by the outer shell. The single quotes aren't relevant at this stage. The outer shell expands $S and the resulting command is:

bash -c " echo '2' "

Then the inner bash command runs and, as you can see, the string being echoed is the fixed string '2' with no variable.

bash -c " echo "$S" "

This looks like it contains quotes inside of quotes, but looks can be deceiving. What you actually have is " echo " adjacent to $S adjacent to " ".

The result is still 2, but I just wanted to point out that this isn't analogous to the bash -c " echo '$S' " case above, which does have nested quotes.

Follow up case

bash -c ' echo "$S" '

You didn't write this form where the outer quotes are single quotes. If you had, you might be puzzled that it doesn't print 2 like the rest. That's weird. Why not?

Answer: Unlike all the versions you posted, this one has the inner shell doing the expansion of $S. The command is single quoted which prevents the outer shell from expanding it, so $S makes it intact to the inner shell. The inner shell, though, doesn't have a variable called $S, and ends up just printing a blank line.

Why doesn't it have S=2? It's because S was not exported. In order for a variable to be visible in a child process it needs to be exported with

export S=2

or

S=2
export S

Unexported variables are only visible in the current process and are unset in child processes.



Answered By - John Kugelman
Answer Checked By - David Goodson (WPSolving Volunteer)