通常、次のプレフィックスを追加してコマンドの環境変数を設定できます。
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
。
答え2
なぜなら$prefix
これは仕事ではないからです。@Jeffはより長い説明を持っています。
関数を使用して同様の操作を実行できます。
$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi
...必要に応じて積み重ねることもできます。
$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123