web-dev-qa-db-ja.com

エクスポートの有無にかかわらず変数を定義する

exportとは何ですか?

違いは何ですか:

export name=value

そして

name=value
818
flybywire

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

あれは、

export name=value

その変数名は 任意のプロセスで利用可能であることを意味します あなたはそのシェルプロセスから実行します。プロセスにこの変数を利用させたい場合は、exportを使用し、そのシェルからプロセスを実行します。

name=value

変数の有効範囲はシェルに限定され、他のプロセスでは使用できないことを意味します。これはループ変数、一時変数などに使用します。

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

904
Brian Agnew

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

$ 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$ 
219
alxp

他の人は、輸出は変数をサブシェルに利用可能にし、それは正しいが単なる副作用であると答えた。変数をエクスポートすると、その変数は現在のシェルの環境に置かれます(すなわち、シェルはputenv(3)またはsetenv(3)を呼び出します)。プロセスの環境はexec全体に継承され、変数はサブシェル内に表示されます。

編集(5年間の観点から):これはばかげた答えです。 'export'の目的は、それらのコマンドがサブシェルであろうとサブプロセスであろうと、変数を「その後に実行されるコマンドの環境内に置く」ことです。単純な実装は単に変数をシェルの環境に置くことですが、これはexport -pを実装することを不可能にします。

67
William Pursell

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

  • Sub shells willは、エクスポートされた状態に関係なく、親からのすべての変数にアクセスできます。
  • Sub processes will onlyエクスポートされた変数を見る。

これら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()が続きます。そのため、fork()が実際にはexec()であると見なすことになります。 execコマンドを使用すると、最初にfork()を実行せずにコマンドを実行できます。このメソッドによって開始されたプロセスも、エクスポートされていない変数にアクセスすることはできません。

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

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

53
Matyas Koszik

サブプロセスにとって意味のある設定と変数については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に感謝します。

28
Charles Merriam

exportは、現在のシェルから分岐したすべてのシェルで変数を使用できるようにします。

10
John T

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

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
9
Brian S. Wilson

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

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

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

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

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

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

Bashの環境 の詳細

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

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

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

Bashのリファレンスマニュアルによると、これも注目に値する。

シェルパラメータ で説明されているように、単純なコマンドや関数の環境は、パラメータ割り当てを接頭辞として追加することで一時的に増強することができます。これらの代入文は、そのコマンドから見た環境にのみ影響します。


まとめると、

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

受け入れられた答え はこれを暗示しているが、私はシェル組み込みへの接続を明示的にしたいと思う。

既に述べたように、exportはシェルと子の両方に変数を利用可能にします。 exportnotを使用している場合、変数はシェル内でのみ使用可能になり、シェル組み込みのみがアクセスできます。

あれは、

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
5
flow2k

これはまた別の例です。

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}"'  

Export VARTESTを使用することによってのみ、VARTESTの値がSudo bash -c '...'で使用可能になります。

さらなる例については、以下を参照してください。

3
soxie

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

私がこれをするならば:

$ MYNAME=Fred
$ export OURNAME=Jim

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

$ env | grep NAME
OURNAME=Jim

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

$ echo $MYNAME
Fred
2
Will

UNIXの2人の作者、Brian KernighanとRob Pikeは、これを彼らの本 "The UNIX Programming Environment"で説明しています。 Googleはタイトルのためにあなたは簡単にpdfバージョンを見つけるでしょう。

それらはセクション3.6のシェル変数を扱い、そのセクションの最後にあるexportコマンドの使用に焦点を当てます。

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

2
Dan Carter

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

1
Scott

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

0
Amjad