元のスクリプトでサブシェルを実行している場合:
(command1; command2; ...)
サブシェルは、 によって作成された元のシェルの直接のコピーであるfork()
ため、使用可能なすべての元の変数の独自のコピーに直接アクセスできます。
サブシェル内のコマンド (command1
などcommand2
) 自体がシェル スクリプトであるとします。これらのコマンドは、サブシェル呼び出しによって実行され、fork()
新しいexec()
シェルを作成します。新しいシェルは、元のシェルからエクスポートされていない変数を継承しません。
あなたの例に直接対処する:
$ a=100
$ (echo $a)
100
$
a
ここで、サブシェルには、親シェルがアクセスしたすべての変数 (具体的には ) の独自のコピーがあります。もちろん、サブシェルで行われた変更は親シェルには反映されないため、次のようになります。
$ a=100
$ (echo $a; a=200; echo $a)
100
200
$ echo $a
100
$
2番目の例:
$ cat b.sh
echo $a
$ a=100
$ ./b.sh
$ . ./b.sh
100
$ source ./b.sh
100
$ a=200 ./b.sh
200
$ echo $a
100
$ export a
$ ./b.sh
100
$
変数a
はエクスポートされないため、初回b.sh
実行時には値がない$a
ため、空の行がエコーされます。次の 2 つの例は「チート」です。b.sh
シェルはスクリプトを現在のシェルの一部であるかのように読み取ります(no fork()
)。そのため、変数は から引き続きアクセスできるためb.sh
、毎回 100 がエコーされます。(ドット or.
は、現在のシェルでスクリプトを読み取るための古いメカニズムです。第 7 版 UNIX の Bourne シェルが使用していました。このsource
コマンドは、同等のメカニズムとして C シェルから借用されています。)
コマンドはコマンドの実行中にa=200 ./b.sh
エクスポートa
するためb.sh
、変更された値を確認してエコーします200
が、メイン シェルはa
変更されていません。がa
エクスポートされると、b.sh
自動的に使用できるようになるため、最後の 100 件が表示され、エコーされます。