環境以外の変数がコマンド置換によって呼び出されたサブシェルに渡されるのはなぜですか?

環境以外の変数がコマンド置換によって呼び出されたサブシェルに渡されるのはなぜですか?

Bashのマニュアルは次のように言います:

コマンドの置換、括弧で囲まれたコマンド、および非同期コマンドは、シェル環境と重複するサブシェル環境で呼び出されます。ただし、シェルによって捕捉されたトラップは、シェルが親シェルから継承した値にリセットされます。祈り。

この例ではb環境変数ではないため、bコマンド置換によって生成されたサブシェルには存在しません。それでは、cコマンド置換で値を割り当てるのはなぜですか?サブシェルが作成され実行される前に、シェルプロセスでパラメータb拡張が発生したためですか?$becho 1

$ b=1
$ c=$(echo $b)
$ echo $c
1

ベストアンサー1

いいえ、サブシェルが最初に作成されます。

シェル実行環境変数の割り当てと環境変数に設定されたシェルパラメータが含まれています。サブシェル環境はシェル環境をコピーして作成されるため、現在のシェル環境のすべての変数が含まれます。

例をご覧ください。

$ b=1
$ c=$(b=2; echo "$b")
$ echo "$c"
2

出力21


コマンド置換によって生成されたサブシェル環境は、シェル実行可能ファイルを呼び出して生成されたシェル環境とは異なります。

シェルを呼び出すとき:

$ 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です。


コマンド置換では、シェルは以下を使用します。クロス()変数セットと環境変数を含む現在のシェル環境を単にコピーする新しいシェルプロセスを作成します。

おすすめ記事