走れば
export TEST=foo
echo $TEST
fooを出力します。
走れば
TEST=foo echo $TEST
いいえ。エクスポートやスクリプトを使用せずにこの機能を取得するにはどうすればよいですか?
答え1
これは、シェルがコマンドラインから変数を拡張するためです。今後実際にコマンドを実行しますが、この時点では変数は存在しません。使用する場合
TEST=foo; echo $TEST
動作します。
export
後で実行されるコマンドの環境に変数が表示されます(bashでこれがどのように機能するかについては、参照help export
)。 1つのコマンド環境にのみ変数を表示する必要がある場合は、試した方法を使用してください。
TEST=foo your-application
シェル構文はこれを次のように説明します。機能的に以下と同じ:
export TEST=foo
your-application
unset TEST
バラより仕様もっと学ぶ。
興味深いことに、このexport
コマンドは変数のエクスポートフラグを切り替えます。名前。その場合は、次のようにしてください。
unset TEST
export TEST
TEST="foo"
TEST
エクスポート時に定義されていない場合でもエクスポートされます。ただし、unset
エクスポートした属性はここで削除する必要があります。
答え2
欲しいと思うシェル変数は環境変数ではなく限られた範囲を持っています。環境変数は、コマンドに渡された文字列のリストです。処刑された。
存在する
var=value echo whatever
var=value
文字列をエコー受信環境に渡します。ただし、echo
環境リストには何も実行されず、ほとんどのシェルにはecho
とにかく組み込まれているため、そうしません。処刑された。
書いたら
var=value sh -c 'echo "$var"'
もう一つの話です。ここではコマンドを渡し、var=value
その環境を使用します。シェルは環境から受け取ったすべての変数をシェル変数に変換するので、受け取った環境変数は変数に変換され、そのコマンドラインから拡張すると環境がデフォルトで継承されるためになります。また、その環境で受信されますが(または実行されている場合)、環境については気にしません。sh
sh
var
sh
$var
echo
echo value
echo
var=value
echo
今私が考えているように、シェル変数の範囲を制限したい場合は、いくつかの可能な方法があります。
ポータブル(BourneとPOSIX):
(var=value; echo "1: $var"); echo "2: $var"
(...)上記はサブシェル(ほとんどのシェルで新しいシェルプロセス)を開始するため、ここで宣言されたすべての変数はそのサブシェルにのみ影響するため、上記のコードでは「1:value」と「2:」または " 2: 以前に設定されたすべての変数"。
ほとんどのBourne型シェルの場合(参照)ローカル変数を定義するために「local」キーワードをサポートするシェルのリスト)、関数と「ローカル」組み込み機能を使用できます。
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
zshを使用すると、次のことができます。匿名関数通常の関数と同様に、ローカル範囲を持つことができます。
(){ local var=value; echo "1: $var"; }; echo "2: $var"
または:
function { local var=value; echo "1: $var"; }; echo "2: $var"
このトリックはbashとzshにも適用されます(ash、pdksh、AT&T kshには適用されません)。
var=value eval 'echo "1: $var"'; echo "2: $var"
より多くのシェル(dash
、、、mksh
)yash
で動作するが動作しないバリエーション(/エミュレーションzsh
を除く):sh
ksh
var=value command eval 'echo "1: $var"'; echo "2: $var"
(POSIXシェルのcommand
特別な組み込み関数(ここ)の前でこれを使用すると、eval
特殊性が削除されます(ここで先行変数の割り当ては戻り後も有効です)。
fish
シェルを使用すると、変数をbegin
..end
ブロックにローカルに設定できます。
begin
set -l var value
echo 1: $var
end
echo 2: $var
mksh
(そしてすぐにzshを使用すると、ローカルスコープも持つ可能性がある${|cmd}
この設定を乱用し、次のスコープ$REPLY
で設定しないようにしてnullに拡張することができます。
${|local var=value; echo "$var"}; echo "$var"
厳密に言えば、これは完全に真実ではありません。一部の実装はローカライズされた環境変数(LANG
、、、LOCPATH
... LC_*
)に興味があり、GNU実装はPOSIXLY_CORRECT
環境変数(GNUシステムとは異なり)env echo --version
に興味があります。env POSIXLY_CORRECT=1 echo --version
答え3
正しく実行していますが、bash構文は簡単に誤解されます。これにより、env varをインポートしてから印刷することにecho $TEST
なると思いますが、そうではありません。だから与えられたecho
TEST
export TEST=123
それから
TEST=456 echo $TEST
次の順序が含まれます。
シェルはコマンドライン全体を解析し、すべての変数置換を実行するので、コマンドラインは次のようになります。
TEST=456 echo 123
コマンドの前に一時変数セットを作成するので、現在の値を保存して
TEST
コマンドラインを456で上書きします。echo 123
残りのコマンドを実行します。この場合、標準出力に123を印刷します(したがって、残りのシェルコマンドに一時値は使用されません
TEST
)。価値を回復させる
TEST
代わりに変数置換を含めないので、printenvを使用してください。
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
答え4
すでに見つけたように、BashではTEST=456 echo $TEST
シェルが現在解釈している同じ行の変数にアクセスしているため、期待どおりに動作しません。でも心配しないでください。変数は、現在のコマンドが継続している間に設定されます。これを確認するには、次のようにします。
show () { echo "${!1}" ;}
TEST=456 show TEST