エクスポートありまたはなしの変数の定義


955

何のexportため?

違いは何ですか:

export name=value

そして

name=value

4
また、export name=value移植性がないことに注意してください。正確に何をしたいかに応じてname=value; export name、ポータブルソリューションを試してください。
tripleee

回答:


1054

export 変数をサブプロセスで使用できるようにします。

あれは、

export name=value

変数名は、そのシェルプロセスから実行するすべてのプロセスで使用できます。プロセスでこの変数を使用する場合は、を使用してexport、そのシェルからプロセスを実行します。

name=value

変数のスコープがシェルに制限されており、他のプロセスでは使用できないことを意味します。これを(たとえば)ループ変数、一時変数などに使用します。

変数をエクスポートしても、親プロセスで使用できるようになるわけではないことに注意してください。つまり、生成されたプロセスで変数を指定してエクスポートしても、その変数を起動したプロセスで使用できるようにはなりません。


105
具体的には、exportは環境を介して子プロセスが変数を使用できるようにします。
Beano

15
また、エクスポートが "ソース"のファイル(。filenameなど)である場合は、作業環境にもエクスポートされることを追加します。
rogerdpack 2013

6
@rogerdpackエクスポートせずにそれを行うことはできませんか?cat> blah \ na = hi \ n。何とか。echo $ a; 「hi」を出力します。
David Winiecki 2013

2
エクスポートなしでも機能します。したがって、ファイルを調達するときに、エクスポートを使用すると、子プロセスに反映されます。そうでない場合、ローカルのbash環境に影響するだけです...
rogerdpack

19
これにはエッジケースが1つあります。name=value command サブプロセス内の変数を利用できるようにしますcommand
Oliver Charlesworth

254

他の答えが言っていることを説明するには:

$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 

9
このためのもう1つの例al$ foobar="Whatever" bash
Alun

70

他の人は、エクスポートによってサブシェルが変数を使用できるようになると回答しています。これは正しいことですが、単なる副作用です。変数をエクスポートすると、その変数は現在のシェルの環境に配置されます(つまり、シェルはputenv(3)またはを呼び出しますsetenv(3))。
プロセスの環境はexec全体で継承され、変数をサブシェルで表示できます。

編集(5年の視点で):これはばかげた答えです。「エクスポート」の目的は、それらのコマンドがサブシェルであろうとサブプロセスであろうと、変数を「後で実行されるコマンドの環境にある」ようにすることです。素朴な実装は、シェルの環境に変数を配置するだけですが、これは実装を不可能にしますexport -pです。


6
これは完全には当てはまりません。ではbash、exportは実際に変数を現在のシェルの環境に追加しますが、ではそうではありませんdash。現在のシェルの環境に変数を追加することが、のセマンティクスを実装する最も簡単な方法であるようにexport思えますが、その動作は必須ではありません。
William Pursell 2013

7
これと何dashが関係しているのかわかりません。オリジナルのポスターは特にについて尋ねていましたbash
ヒトデ2013

14
質問にはタグbashが付けられていますが、ボーンシェルバリアントにも同様に適用されます。過度に具体的であり、それにのみ当てはまる回答を提供することbashは、大きな悪です。
William Pursell 2013

12
bashシェルのjQueryです。
Potherca 2014年

2
export makes the variable available to subshells, and that is correctこれは非常に混乱する用語の使い方です。サブシェルはexport変数を継承する必要はありません。サブプロセスは行います。
アミットナイ

62

サブシェルをスポーンするときにbashでエクスポートする必要はないと言われていますが、反対の意見もあります。それはサブシェルとの違いに注意することが重要である(によって作成されたものを()``$()またはループ)とサブプロセス(例えば、名前によって呼び出されたプロセスリテラルbashスクリプトに登場します)。

  • サブシェルは なり関わらず、エクスポート状態の、親からすべての変数にアクセスすることができます。
  • サブプロセスには、エクスポートされた変数のみが表示されます。

これらの2つの構成に共通するのは、どちらも変数を親シェルに戻すことができないことです。

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:

混乱の原因がもう1つあります。「フォークされた」サブプロセスは、エクスポートされていない変数が表示されないサブプロセスであると考える人もいます。通常、fork()の直後にexec()が続きます。そのため、実際にはexec()であるのに対し、fork()が検索対象であるように見えます。最初にfork()を実行せずにコマンドを実行できます。execこのメソッドで開始されたプロセスも、エクスポートされていない変数にアクセスできません。

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

parent:今回は親シェルをexecコマンドに置き換えたため、この行は表示されないことに注意してください。そのため、そのコマンドを実行するために残っているものはありません。


(それ自体で)サブシェルを作成するループを見たことがありません。パイプラインが行うOTOH(シェル、バージョン、オプションに応じて、常に最後以外の部分、場合によっては最後の部分)。背景(&)もサブシェルを作成します。
dave_thompson_085

これらはvar=asdf bash -c 'echo $var'どうvar=asdf exec bash -c 'echo $var'ですか?出力はasdfです。;変数定義の後に置かれた場合の違いになります。説明は何でしょうか?それは次のようになりますvar(なしで;原点シェルのために何らかの形で生成されたサブプロセスに関して、)それとは何の関係もありません。echo $var2行目に実行しても何も出力されません。しかし、裏地var=asdf bash -c 'echo $var'; echo $varが1つありますasdf\nasdf
4xy

31

export NAME=value サブプロセスにとって意味のある設定と変数の場合。

NAME=value 現在のシェルプロセス専用の一時変数またはループ変数の場合。

より詳細にexportは、作成時にサブプロセスとそのサブプロセスにコピーする環境で変数名をマークします。名前や値がサブプロセスからコピーされることはありません。

  • 一般的なエラーは、等号の周りにスペースを置くことです:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
  • エクスポートされた変数(B)のみがサブプロセスに表示されます。

    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
  • サブプロセスを変更しても、メインシェルは変更されません。

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
  • エクスポート用にマークされた変数には、サブプロセスの作成時に値がコピーされます。

    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
  • エクスポートされた変数のみが環境の一部になります(man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob

だから、今は夏の太陽と同じくらいはっきりしているはずです!Brain Agnew、alexp、およびWilliam Prusellに感謝します。


12

export 現在のシェルからフォークされたすべてのシェルで変数を使用できるようにします。


11

変数をエクスポートして後で値を変更できることに注意してください。変数の変更された値は、子プロセスで使用できます。変数にエクスポートを設定したらexport -n <var>、プロパティを削除する必要があります。

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset

おかげで、これはまさに私が探していた情報です。環境変数を使用するスクリプトを見た後、新しい値を使用してそれらを「再エクスポート」し、必要かどうか疑問に思っていたからです。
Mike Lippert、2016年

8

ご存知かもしれませんが、UNIXではプロセスに一連の環境変数(キーと値のペアで、キーと値の両方が文字列)を含めることができます。オペレーティングシステムは、これらのペアをプロセスごとに個別に保持する責任があります。

プログラムは、次のUNIX APIを介して環境変数にアクセスできます。

  • char *getenv(const char *name);
  • int setenv(const char *name, const char *value, int override);
  • int unsetenv(const char *name);

プロセスは、親プロセスから環境変数も継承します。オペレーティングシステムは、子プロセスの作成時にすべての「envars」のコピーを作成する責任があります。

Bashは、他のシェルの中でも、ユーザーの要求に応じて環境変数を設定できます。これがexport存在する理由です。

exportBashの環境変数を設定するBashコマンドです。このコマンドで設定されたすべての変数は、このBashが作成するすべてのプロセスに継承されます。

バッシュの環境の詳細

Bashの別の種類の変数は内部変数です。Bashは単なるインタラクティブシェルではないため、実際には他のインタープリター(Pythonなど)と同様にスクリプトインタープリターであり、独自の変数のセットを保持できます。Bashは(Pythonとは異なり)文字列変数のみをサポートしていることに注意してください。

Bash変数を定義するための表記はname=valueです。これらの変数はBash内にとどまり、オペレーティングシステムによって保持される環境変数とは何の関係もありません。

シェルパラメータの詳細(変数を含む)

また、Bashリファレンスマニュアルによると、注目に値します。

シェルパラメータで説明されているように、単純なコマンドまたは関数の環境は、パラメータ割り当てを前に付けることによって一時的に拡張できます。これらの割り当てステートメントは、そのコマンドが認識する環境にのみ影響します。


まとめると:

  • exportオペレーティングシステムの環境変数を設定するために使用されます。この変数は、現在のBashプロセスによって作成されたすべての子プロセスで使用できます。
  • bash変数表記(name = value)は、bashの現在のプロセスでのみ使用可能なローカル変数を設定するために使用されます
  • 別のコマンドの前にBash変数の表記を付けると、そのコマンドのスコープに対してのみ環境変数が作成されます。

1
bash変数はPythonほど多くの型をサポートしていませんが、文字列、整数、および2種類の配列(「インデックス付き」/従来型および「連想型」は、awk配列、perlハッシュ、またはPython dictに似ています)を持っています。他のシェルは異なります。文字列のみが移植可能です。
dave_thompson_085 2017

7

受け入れられた答えは、このことを意味しますが、私はシェル組み込みコマンドへの明示的な接続をしたいのですが。

すでに述べたようにexport、シェルと子の両方が変数を使用できるようにします。exportが使用されていない場合、変数はシェルでのみ使用可能であり、シェルのビルトインのみが変数にアクセスできます。

あれは、

tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin

3

さらに別の例を次に示します。

VARTEST="value of VARTEST" 
#export VARTEST="value of VARTEST" 
sudo env | grep -i vartest 
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'  

VARTESTのエクスポートを使用することによってのみ、VARTESTの値をsudo bash -c '...'で使用できます。

その他の例については、以下を参照してください。


3

UNIXの作成者の2人、Brian KernighanとRob Pikeは、彼らの著書「The UNIX Programming Environment」でこれを説明しています。タイトルにGoogleを使用すると、PDFバージョンを簡単に見つけることができます。

それらはセクション3.6でシェル変数を扱い、exportそのセクションの終わりでコマンドの使用に焦点を合わせます:

変数の値をサブシェルでアクセスできるようにするには、シェルのエクスポートコマンドを使用する必要があります。(サブシェルからその親に変数の値をエクスポートする方法がない理由について考えるかもしれません)。


2

エクスポートされた変数が環境(env)にあることと、エクスポートされていない変数が環境にないことの違いを示すだけです。

私がこれをすると:

$ MYNAME=Fred
$ export OURNAME=Jim

その場合、$ OURNAMEのみが環境変数に表示されます。変数$ MYNAMEが環境にありません。

$ env | grep NAME
OURNAME=Jim

変数$ MYNAMEはシェルに存在します

$ echo $MYNAME
Fred

1

デフォルトでは、スクリプト内で作成された変数は、現在のシェルでのみ使用できます。子プロセス(サブシェル)は、設定または変更された値にアクセスできません。子プロセスが値を表示できるようにするには、exportコマンドを使用する必要があります。


0

説明では明示的に言及していませんが、すべての変数が子プロセスにコピーされるため、bash内からサブシェルを生成するときにエクスポートを使用する必要はありません。


あなたの言っていることが上記の例の答えと直接矛盾するように思われるので説明してください。
Mike Lippert、2013年

変数をグローバルにエクスポートしたくないが、サブプロセスでのみ使用できるようにする場合は、これが正しい方法です。ありがとうございました。
jtblin 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.