web-dev-qa-db-ja.com

メインシェルにエクスポートせずにサブシェルに継承された変数

私は以下のシェルスクリプトを持っています

var="this is a test"

ls -ltr| while read file
do
     echo $var
done
echo $var

以下の出力が得られます。

this is a test
this is a test
this is a test

パイピングによって新しいサブシェルが生成され、メインシェルで「var」変数をエクスポートしないため、whileループ内で変数「var」の値を「thisisatest」に設定するにはどうすればよいですか。

私の知る限り、子が親シェルから変数値を継承するには、変数をエクスポートする必要がありますが、この場合、変数値は「export」ステートメントなしで継承されます。

2
Pankaj Pandey

Bashマニュアルの内容を見てみましょう( .7.3コマンド実行環境

シェルには、以下で構成される実行環境があります。

  • 変数の割り当てによって設定されるシェルパラメータまたは環境内のシェルの親から設定または継承されたもの
  • 実行中に定義された、または環境内のシェルの親から継承されたシェル関数

コマンド置換、括弧でグループ化されたコマンド、および非同期コマンドは、シェル環境の複製であるサブシェル環境 [...]で呼び出されます。

サブシェル環境に加えられた変更は、シェルの実行環境に影響を与えることはできません。

.2.2パイプライン では、それも言われています

パイプラインの各コマンドは、独自のサブシェルで実行されます

(もちろん、これはマルチコマンドパイプラインにのみ適用されます)

したがって、パイプラインの一部と他のサブシェルは、allシェル変数のコピーを取得しますが、それらへの変更はnotシェルの外側から見える。

他のコマンドでは、exportを実行する必要があります。

ビルトイン関数やシェル関数以外の単純なコマンドを実行する場合は、以下からなる別の実行環境で呼び出されます。

  • エクスポート用にマークされたシェル変数と関数、コマンド用にエクスポートされた変数とともに、環境に渡されます

思考の糧:この印刷物は何ですか?

bash -c 'f() { echo "$a $b"; }; a=1; b=1; (b=2; f); f'
3
ilkkachu