Execution by subshell (and variable update)

Hello. Here's a quick summary of what happens when run by a subshell:

  1. When the command is enclosed in parentheses "()" [^ 1].
  2. Before and after the pipeline.
  3. When a character string / text is passed to a shell command and executed [^ 2].

Command group

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.

Execution example by subshell

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
  1. What is executed in the original shell is:
  1. What is executed in the subshell is:

Variable update in subshell

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

$ 

Avoid "update variables in subshell"

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
$

Use of "Here Document"

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

Execution by subshell (and variable update)
Java compilation and execution understood by CLI
Notify error and execution completion by LINE [Python]
Command execution triggered by file update (python edition)
pytube execution and error
Visualization method of data by explanatory variable and objective variable
[Road to Python intermediate] Dynamically specify execution method by variable name