4

最近、私は高度な Bash スクリプトを読んでいて、親シェルと子シェルの間の可変スコープについて何かを見つけて、とても困惑しています。ここにあります:

シーン: 子シェルを生成するにはいくつかの方法があります: 最初に、(command-lists); 次に、非組み込みコマンドまたはスクリプトを実行します。

親スクリプトでスクリプトを実行すると、子スクリプトは親シェルの変数を見ることができないためです。(command-lists)構造体で子シェルが親シェルの変数を見ることができるのはなぜですか。例えば

  1. (コマンドリスト)

    $ a=100
    $ (echo $a)
    100
    $
    
  2. スクリプトを実行する

    $ cat b.sh
    echo $a
    $ a=100
    $ ./b.sh
    # empty
    

どのように?

4

1 に答える 1

8

元のスクリプトでサブシェルを実行している場合:

(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 件が表示され、エコーされます。

于 2013-05-20T15:42:50.177 に答える