元のスクリプトでサブシェルを実行している場合:
(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 件が表示され、エコーされます。