web-dev-qa-db-ja.com

パイプ内の2番目のコマンドでbash内のコマンドが機能しない前に環境変数を設定する

与えられたシェルでは、通常私は変数を設定してからコマンドを実行します。最近、変数定義をコマンドの前に付けるという概念について学びました。

FOO=bar somecommand someargs

これはうまくいく…。 LC_ *変数を変更するとき(これはコマンドには影響しますが、引数には影響しないようです。たとえば '[a-z]'の文字範囲)、または出力を別のコマンドにパイプ処理するときにはうまくいきません。

FOO=bar somecommand someargs | somecommand2  # somecommand2 is unaware of FOO

Somecommand2の前に "FOO = bar"を追加することもできますが、これは機能しますが、不要な複製が追加され、変数に応じて解釈される引数には役立ちません(たとえば '[a-z]')。

それで、これを一行で行うための良い方法は何ですか?私は次の順序で何かを考えています。

FOO=bar (somecommand someargs | somecommand2)  # Doesn't actually work

編集:私はたくさんの良い答えを得ました!目標は、できれば「エクスポート」を使用せずにこれをワンライナーにすることです。 bashの呼び出しを使用する方法は全体的に最も優れていましたが、「export」を含む括弧付きのバージョンはもう少しコンパクトです。パイプではなくリダイレ​​クトを使用する方法も興味深いです。

304
MartyMacGyver
FOO=bar bash -c 'somecommand someargs | somecommand2'
263

サブシェルの中だけで、変数をエクスポートしてはどうでしょうか。

(export FOO=bar && somecommand someargs | somecommand2)

Keithには無条件にコマンドを実行するというポイントがあります。

(export FOO=bar; somecommand someargs | somecommand2)
181
0xC0000022L

evalを使用することもできます。

FOO=bar eval 'somecommand someargs | somecommand2'

evalを使ったこの答えは誰もが喜ばないようなので、何かを明確にさせてください。書かれたように使われるとき、一重引用符で、それは完全に安全です。外部プロセスを起動しない(受け入れられた答えのように)ことも、余分なサブシェルでコマンドを実行することもない(他の答えのように)ので、それは良いことです。

私たちがいくつかの定期的な見解を得るとき、それは皆を喜ばせ、そしてこの素早いeval「トリック」のすべての利益(そしておそらくもっと!)を持っているevalの代わりを与えることはおそらく良いでしょう。関数を使うだけ!すべてのコマンドで関数を定義してください。

mypipe() {
    somecommand someargs | somecommand2
}

そして、このようにあなたの環境変数でそれを実行してください:

FOO=bar mypipe
38
gniourf_gniourf

envを使用します。

たとえば、env FOO=BAR commandcommandの実行が終了すると、環境変数が再び復元/変更されないことに注意してください。

シェルの置換の発生に注意してください。つまり、同じコマンドラインで$FOOを明示的に参照する場合は、シェルインタープリターが置換を実行しないようにエスケープする必要がある場合がありますbeforeenvを実行します。

$ export FOO=BAR
$ env FOO=FUBAR bash -c 'echo $FOO'
FUBAR
$ echo $FOO
BAR
3
benjimin