Bashのマニュアルは次のように言います:
コマンドの置換、括弧で囲まれたコマンド、および非同期コマンドは、シェル環境と重複するサブシェル環境で呼び出されます。ただし、シェルによって捕捉されたトラップは、シェルが親シェルから継承した値にリセットされます。祈り。
この例ではb
環境変数ではないため、b
コマンド置換によって生成されたサブシェルには存在しません。それでは、c
コマンド置換で値を割り当てるのはなぜですか?サブシェルが作成され実行される前に、シェルプロセスでパラメータb
拡張が発生したためですか?$b
echo 1
$ b=1
$ c=$(echo $b)
$ echo $c
1
答え1
いいえ、サブシェルが最初に作成されます。
ㅏシェル実行環境変数の割り当てと環境変数に設定されたシェルパラメータが含まれています。サブシェル環境はシェル環境をコピーして作成されるため、現在のシェル環境のすべての変数が含まれます。
例をご覧ください。
$ b=1
$ c=$(b=2; echo "$b")
$ echo "$c"
2
出力2
は1
。
コマンド置換によって生成されたサブシェル環境は、シェル実行可能ファイルを呼び出して生成されたシェル環境とは異なります。
シェルを呼び出すとき:
$ bash -c :
現在使用中のシェル実装する()たとえば、次のように新しいシェルプロセスを作成します。
execve("/bin/bash", ["bash", "-c", ":"], [/* 64 vars */]) = 0
最後に渡されたパラメータにはexecve
すべての環境変数が含まれます。
それがあなたが必要な理由です。出口後で実行されるコマンドに含まれる環境変数にプッシュする変数:
$ a=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++
環境変数が64から65に変更されました。そして、エクスポートされていない変数は新しいシェル環境に渡されません。
$ a=; b=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++
環境変数はまだ65です。
コマンド置換では、シェルは以下を使用します。クロス()変数セットと環境変数を含む現在のシェル環境を単にコピーする新しいシェルプロセスを作成します。
答え2
例bは環境変数ではありません。
ただし、はい、bはコマンド置換によって生成されたサブシェルに存在します。
$ b=11; c="$(echo $b)"; echo "$c" ### b exists in subshell.
11
$ b=11; c="$(b=33; echo $b)"; echo "$c" ### $b is not replaced before
33 ### the subshell is executed.
$ b=11; bash -c 'echo "<$b>"' ### b does not exist.
<>
$ b=11 bash -c 'echo "<$b>"' ### environment b.
<11>
もちろん、そのプロセスは環境から変数を受け取ることができることは除外されます。
最後の行は次の位置にあります。ウールウィッチエッグシェル:
サブシェル内では汎用シェル変数aが表示されますが、エクスポートされないため、サブプロセス全体には表示されません。
答え3
コマンドの置き換えにより、シェルインタプリタが正常に呼び出され、インタプリタecho
はsub-process
。
これは、シェルが結果を読み取れるようにコマンドを作成する必要があるsub-process
ために必要です。pipe
echo
sub-process
このコマンドを実行すると、デフォルトのシェルプロセス内のすべての変数のコピーが作成されますecho
。fork()
そのため、コマンドを介して$b
アクセスできます。echo