set、export、envの違いは何ですか?それぞれをいつ使用する必要がありますか?


112

頻繁にbashスクリプトをバッシュアウトしますが、変数を設定する方法がいくつかあります。

key=value
env key=value
export key=value

スクリプトまたは単一のコマンド(たとえば、多くの場合、適切なWineプレフィックスを設定するために変数をWineランチャーにチェーンします)の中にいる場合、これらは完全に互換性があるように見えますが、確かにそうではありません。

これら3つの方法の違いは何ですか。それぞれの方法を具体的に使用したい場合の例を教えてください。

確かに関連した`VAR = ...`と`輸出VAR = ...`の違いは何ですか?しかし、私はenvこれにもどのように適合するかを知りたいです、そしてそれぞれの利点を示すいくつかの例もいいでしょう


5
export key=value構文を拡張し、ポータブルスクリプト(IEで使用すべきではありません#! /bin/sh)。
サイモンリヒター

回答:


110

特定の例を考えてみましょう。このgrepコマンドは、GREP_OPTIONSデフォルトオプションを設定するために呼び出される環境変数を使用します。

今。ファイルtest.txtに次の行が含まれている場合:

line one
line two

コマンドgrep one test.txtを実行すると戻ります

line one

オプションを指定してgrepを実行すると、-v一致しない行が返されるため、出力は

line two

次に、環境変数を使用してオプションを設定しようとします。

  1. なしで設定された環境変数exportは、呼び出しているコマンドの環境に継承されません。

    GREP_OPTIONS='-v'
    grep one test.txt
    

    結果:

    line one

    明らかに、オプション-vはに渡されませんでしたgrep

    使用したいシェルだけに変数を設定しているとき、たとえばfor i in * ; doエクスポートしたくないときにこのフォームを使用します$i

  2. ただし、変数はその特定のコマンドラインの環境に渡されるため、次のことができます。

    GREP_OPTIONS='-v' grep one test.txt

    期待値を返します

    line two

    このフォームを使用して、起動したプログラムのこの特定のインスタンスの環境を一時的に変更します。

  3. 変数をエクスポートすると、変数が継承されます。

    export GREP_OPTIONS='-v'
    grep one test.txt
    

    すぐに戻ります

    line two

    これは、シェルで後で開始されるプロセスを使用するための変数を設定する最も一般的な方法です

  4. これはすべてbashで行われました。exportbashビルトインです。VAR=whateverbash構文です。env、他方では、それ自体がプログラムです。ときenvに呼び出され、次のことが起こります:

    1. コマンドenvは新しいプロセスとして実行されます
    2. env 環境を変更し、
    3. 引数として提供されたコマンドを呼び出します。envプロセスが置き換えられているcommandプロセス。

    例:

    env GREP_OPTIONS='-v' grep one test.txt

    このコマンドは、(i)envおよび(ii)grepの2つの新しいプロセスを起動します(実際には、2番目のプロセスが最初のプロセスを置き換えます)。grepプロセスの観点から見ると、結果は実行とまったく同じです。

    GREP_OPTIONS='-v' grep one test.txt

    ただし、bashの外にいる場合、または別のシェルを起動したくない場合(たとえば、呼び出しexec()ではなく関数ファミリーを使用している場合)、このイディオムを使用できますsystem()

追加の注意事項 #!/usr/bin/env

これはまた、イディオム#!/usr/bin/env interpreterが使われるよりも使われる理由です#!/usr/bin/interpreter。シェルのように変数を検索 し、コマンドの実行によってそれ自体を置き換える関数をenv使用するため、プログラムへのフルパスは必要ありません。したがって、これはインタープリター(perlやpythonなど)がパス上の「座っている」場所を見つけるために使用できます。execvp()PATH

また、現在のパスを変更することにより、どのpythonバリアントが呼び出されるかに影響を与えることができることを意味します。これにより、次のことが可能になります。

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

Calibreを起動する代わりに、

I am an evil interpreter!

GREP_OPTIONS = '-v' grep one test.txtが機能するのはなぜですか?'-v'の後にセミコロンが必要だと思った(しかし、試してみたが、実際に機能する。)
ジョー

2
セミコロンを使用すると、2つの別個のbashコマンドとして解釈されるためです。最初の変数は(変数をエクスポートせずに)変数を設定し、2番目の変数は変数がエクスポートされていない環境で開始します。ただし、セミコロンを使用しない場合、これは1つのコマンド(grep)であり、その前にローカル環境を設定します。

すべての変数はどこからenv来たのですか?新しいシェルを開くと、常にいくつかの変数があります。それで、いくつかのプログラムはexportそれらを編集したに違いありませんか?
ピチコス

1
@Pithikos環境変数は「環境の調達」によって設定されます。デフォルトでは、bashはシステム全体のbashrc(またはprofile.dまたはbash_profile)をソースします。次に、ユーザー〜/ .bashrc(および/または〜/ .bash_profile)を取得します。これらのファイルのいずれかに、他のスクリプトのソースとなるbashコマンドを含めることができるため、最終的には環境変数をあらゆる場所から取得できます。
エリック

5
どうset var=blah
CMCDragonkai
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.