Hello. Here's a quick summary of what happens when run by a subshell:
If you make it a command group (that is, enclose it in brace "{}"), it will be treated as a single execution unit, and it will be executed in the original shell as it is [^ 3]. There are also functions and while do ~ done
[^ 4] to handle similar chunks.
The combination of pipelines and command groups was easy to misunderstand. If you read the example below,
command1; command2; { command3; command4; } | { commmand5; command6; }; command7; command8
command1, command2
command7, command8
command3, command4
command5, command6
Next, considering the variable update in the subshell, this does not propagate to the original shell. In the example below, the output of echo $ n
at the end will be empty.
$ unset n; { n=0; printf 'a\nb\n'; } | cat; echo $n
a
b
$ unset n; printf 'a\nb\n' | (n=0; while read -r line; do n=$((n+1)); done; echo $n); echo $n
2
$ unset n; printf 'a\nb\n' | { n=0; while read -r line; do n=$((n+1)); done; echo $n; }; echo $n
2
$
If you update variables in the original shell, you can avoid "update variables in subshells". The example below is crowded, but `` n = 0``` is executed in the original shell and the output of the trailing ```echo $ n``` is ```
0```.
$ unset n; { n=0; printf 'a\nb\n' | cat; } ; echo $n
a
b
0
$
Similarly, you can use a "here document" to update variables in the original shell (you can avoid the pipeline). In the example below, the output of echo $ n
at the end will be `` `2```.
$ unset n; { n=0; while read -r line; do n=$((n+1)); done << EOT
$(printf 'a\nb\n')
EOT
echo $n; }; echo $n
2
2
$
Alternatively, you can use Process Substitution in Bash etc. instead of POSIX shell:
$ unset n; { n=0; while read -r line; do n=$((n+1)); done < <(printf 'a\nb\n'); echo $n; }; echo $n
2
2
$
[^ 1]: The format of $ (...)` `` to get the standard output of the subshell execution enclosed in parentheses" () "is similar. However, the form
$ ((...))` `` is executed in the original shell ("Variables in subshell").
[^ 2]: Refers to an execution example such as executing a shell script or `sh -c'n = 0; echo $ n'
`. On the other hand, if you run it with the source
command, it will be executed in the original shell.
[^ 3]: This is similar to enclosing in parentheses "()", but it is not treated as a subshell.
[^ 4]: For example, `` `printf'a \ nb \ n'| while read -r line; do echo $ line; done```.
Recommended Posts