次のような変数をエクスポートするスクリプトがあるとします。
#!/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
スペースやその他のシェルメタ文字を渡します。
また、見ることができますシェルの制御およびリダイレクト演算子は何ですか?