変数をコマンドプレフィックスとして使用して環境変数を設定できないのはなぜですか?

変数をコマンドプレフィックスとして使用して環境変数を設定できないのはなぜですか?

通常、次のプレフィックスを追加してコマンドの環境変数を設定できます。

hello=hi bash -c 'echo $hello'

また、変数を使用して、次のようにコマンド呼び出しの一部を置き換えることができることもわかります。

$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"

変数をコマンドプレフィックスとして使用して環境変数を設定できないことに非常に驚きました。テストケース:

$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found

変数を使用して環境変数を設定できないのはなぜですか?プレフィックス部分は特別な部分ですか? evalを事前に使用して動作させることができますが、それでも理由を理解していません。私はbash 4.4を使用しています。

ベストアンサー1

私はこれがあなたにとって魅力的な順序の一部だと思います。

変数の割り当てやリダイレクト以外の単語は拡張されます(シェル拡張を参照)。拡張後もまだ単語がある場合、最初の単語はコマンド名として扱われ、残りの単語は引数として扱われます。

それが出身です。バッシュリファレンスマニュアル単純コマンド拡張セクションで。

この例では、cmd=bash環境変数は設定されておらず、bashはパラメータ拡張を介してコマンドラインを処理しますbash -c "echo hi"

このprefix=hello=hi例では、最初のパスに変数の割り当てがないため、パラメータ拡張で処理が続行され、最初の単語が生成されますhello=hi

変数の割り当てが処理されると、コマンド実行中に再処理されません。

以下で処理と結果を確認してくださいset -x

$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42

「環境変数」のより安全なバリアントである「変数拡張」の場合は、eval次の点を考慮してください。ビザンドリアのアドバイスenv:

prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi

厳密に言えば、ユーティリティの主な機能を使用してコマンドに環境変数を割り当てるので、これはコマンドライン変数の割り当てではありませんが、env同じ目標を達成します。変数は$prefixコマンドライン処理中に拡張され、name = valueを提供しenvてから渡されますbash

おすすめ記事