シェルからエクスポートされた変数の範囲

シェルからエクスポートされた変数の範囲

次のような変数をエクスポートするスクリプトがあるとします。

#!/bin/bash
foo(){
    eval export one=1
}
foo1(){
    eval export two=2
}
(foo)
foo1
echo "one=$one"
echo "two=$two"

しかし、私は次のような結果を得ます。

root@centos1:~>/tmp/test.sh
one=
two=2 

値を見ることはできませんが、$one見ることができるのはなぜですか$two

答え1

グローバル変数設定された瞬間から設定が解除されるか、プロセスが終了する瞬間まで続きます。グローバル(またはローカル)変数は、関連していない子プロセスによって継承されません(サブプロセスがフォーク(サブシェル)の場合、エクスポートまたはエクスポートされていないすべてのもののコピーを取得します)。

グローバル輸出変数グローバル変数に似ていますが、子プロセス(関連していない子プロセスも含む)によって自動的に継承されます(プロセス環境の一部として)。 (エクスポートを使用すると、CXXFLAGS同じプロセスに同じ変数を渡すことができますmake。これは間違いなくシェルのサブシェルではなく、生成されたmakeすべてのプロセスもその変数を取得します。)

あなたの例では、()すべてのもののコピーを取得するサブシェルを作成します。このfooコマンドは、エクスポートした変数を追加してサブシェルを変更し、エクスポートした変数を使用せずにサブシェルを終了します(孫なし)。これで、子プロセスから親プロセスに暗黙的に情報が送信されなくなります。子供たちが自分の環境でやっていることは親に影響を与えません。これが変数がone設定されていない理由です。


ところで、この場合はeval必要ありません。eval

答え2

コマンドを束ねると、( )そのコマンドはサブシェルにあります。

これは、パイプやシャットダウンが必要な場合に便利です。

たとえば、次のコマンドは

( date ; cmd1 ; cmd2 ) | grep ...

最初の3つのコマンドが接続されて出力をgrep

これを{ }行うには、bashのマニュアルページ(bash(1));これは抜粋です:

(list)

    listサブシェル環境で実行されます(参照:コマンド実行環境 次のような)。シェル環境に影響を与える変数割り当ておよび組み込みコマンドは、コマンドの完了後に無効になります。戻り状態は終了状態です。list

{ list; }

    list現在のシェル環境で実行できます。  list改行またはセミコロンで終了する必要があります。これは…グループコマンド。  戻り状態は終了状態です。list。メタ文字とは異なり(そして)、 { そして }はい予約語そして必ず起こらなければならない 予約語 認められるようにしてください。単語の分離を引き起こさないので、次のように組み合わせる必要があります。listスペースやその他のシェルメタ文字を渡します。

また、見ることができますシェルの制御およびリダイレクト演算子は何ですか?

関連情報