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

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

次のシェルスクリプトがあります

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」変数の値を「this is a test」に設定するにはどうすればよいですか?

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

答え1

Bashマニュアルに何と書かれているのか見てみましょう(3.7.3 コマンド実行環境)

シェルには、次の部分で構成される実行環境があります。

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

コマンドの置換、括弧で囲まれたコマンド、および非同期コマンドは、次のように呼び出されます。サブシェル環境はシェル環境のコピーです。[...]

サブシェル環境への変更は、シェルの実行環境には影響しません。

存在する3.2.2 パイプライン、ともいう

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

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

したがって、パイプラインのさまざまな部分と他のサブシェルは次のコピーを取得します。みんなシェル変数ですが、これに対するすべての変更はいいえシェルに表示されます。

他のコマンドの場合はまだ必要ですexport

組み込み関数やシェル関数ではなく単純なコマンドを実行したい場合は、次のように構成された別の実行環境で呼び出されます。

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

考えるべきこと: これは何を印刷するか。

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

関連情報