10

I am reading a Linux shell scripting book and have found the following warning:

"Command substitution creates what's called a subshell to run the enclosed command. A subshell is separate child shell generated from the shell that's running the script. Because of that, any variables you create in the script aren't available to the subshell command".

I have tried to create a variable in my current bash shell's CLI and then enter the subshell to check whether I can print it on the screen. So yes, I can't do it, seems to be according the citation above. However, I have run the following script with command substitution:

#!/bin/bash
var=5.5555
ans=$(echo $var)
echo $ans

And the result is:

5.5555

As I understood, it shouldn't print the value of var since the subshell shouldn't be able to "see it". Why does it happen?

Lesmana
  • 27,439
Donatas
  • 255
  • But the comment in the book says it does. I even included $BASH_SUBSHELL variable to print out in the command substitution and it printed 1 which means it created a subshell. – Donatas Sep 12 '16 at 07:54
  • 4
    Your book isn't very good. – Michael Homer Sep 12 '16 at 08:32
  • "Linux Command Line and Shell Scripting Bible" written by Richard Blum and Christine Bresnahan. I found it pretty comprehensive and haven't got doubts up to this point. – Donatas Sep 12 '16 at 08:37
  • 1
    At the very least that statement is unclear and misleading, and otherwise it's just outright wrong, as you've demonstrated in this question. – Michael Homer Sep 12 '16 at 08:40
  • 1
    Charitably I'd have to guess that the book means "are not available for assignment" (with the thinking that that means the "variable" is unavailable), but it's a very unhelpful way of saying so if that's really what they meant. – Michael Homer Sep 12 '16 at 08:41
  • 1
    Read some of our questions on [tag:sushell], such as http://unix.stackexchange.com/questions/157957/why-is-a-variable-visible-in-a-subshell and http://unix.stackexchange.com/questions/138463/do-parentheses-really-put-the-command-in-a-subshell – Gilles 'SO- stop being evil' Sep 12 '16 at 08:41

2 Answers2

13

The statement:

Because of that, any variables you create in the script aren't available to the subshell command.

is false. The scope of a variable defined in the parent shell is the entire script (including subshells created with command substitution).

Running:

#!/bin/bash
var=5.5555
ans1=$(echo $var)
ans2=$(var=6; echo $var)
echo $ans1
echo $ans2

will give the result:

5.5555
6

$var is resolved by the subshell:

  • if no local variable is specified, the value of three global variable is used
  • if a local variable is specified, it uses its value

See also the example 21-2.

techraf
  • 5,941
11

The statement as quoted is not true. It is also not true that the variable has been pre-substituted before the subshell runs.

You can validate this directly using variable indirection:

$ x=hello
$ echo Result is $(y=x ; echo ${!y} ; echo world)
Result is hello world

The variable x is definitely available directly to the subshell (rather than having had its value previously expanded) because ${!y} reads from the variable whose name is stored in y - which didn't exist at the time the subshell was created.


A charitable reading of the passage from the book would be that it means to say that the "variable" is unavailable because you can't modify its value persistently. Any variable assignments you make within a subshell are not available to the parent shell afterwards, whether that's making new variables (like y) or assigning replacement values to existing variables. If the subshell assigned to x, the new value would have effect inside the subshell, but reading from it afterwards would give the original value:

$ x=world
$ echo $(x=hello ; echo $x)
hello
$ echo $x
world

It's not a very clear way of expressing that, at least in the passage you've quoted. If the whole book is like that, you may be able to find a better one (or read questions here instead).

Michael Homer
  • 76,565