Assigning values by doing multiple commands per bash test statement not work

Viewed 55

When I want to issue multiple command by using bash test statement with subshell, this works:

a=255
 b=0
 [[ a -eq 255 ]] && ( echo $a;echo $b )
255
0

But why assign values not work?

[[ a -eq 255 ]] && ( a=0;b=255 )
 echo $a
255

 echo $b
0

I know if I change the parenthesis to bracket, it works, and I just want to know why it doesn't work when assigning values.

2 Answers

First of all, take a look at the man bash:

Placing a list of commands between parentheses causes a subshell environment to be created (see Command Execution Environment), and each of the commands in list to be executed in that subshell. Since the list is executed in a subshell, variable assignments do not remain in effect after the subshell completes.

When subshell's executed it creates its own set of variables that are not visible to any other shell, but { list; } is executed in the current shell, so these variables are visible, you can make sure using declare built-in command:

echo "spawn a subshell"
( (declare sub_local=100; declare -p | grep sub_local) )

echo "current shell"
declare -p | grep sub_local

The current shell and the subshell that is spawned from the () syntax share the same stdout but are two different processes with different pids etc. This means that defining a variable a at the child process (subshell) doesn't affect the value of the variable a as defined at the parent process. In other words variable is not a shared resource between the two different processes. The following example describes this behavior:

Example

# script
echo "parent pid: $BASHPID";
a=255;
echo "(parent) a before: $a";
[[ a -eq 255 ]] && ( echo "subshell pid: $BASHPID"; \
                     echo "(subshell) a before: $a"; \
                     a=0; \
                     echo "(subshell) a after: $a"; \
                     b=255; )
echo "(parent) a after: $a"

# Output
parent pid: 839
(parent) a before: 255
subshell pid: 901
(subshell) a before: 255
(subshell) a after: 0
(parent) a after: 255
Related