$()
bashは構文または構文を介してトークンを置き換えます``
。たとえば、次のようになります。
$ $(echo "echo hi")
hi
AFAIK、その仕組みは次のとおりです。
- まず、内部コマンドであることを評価します。
echo "echo hi"
その出力は次のようになります。echo hi
- 結果の文字列は、以下を
echo hi
生成するコマンドで実行されます。hi
それでは、以下をhi
ファイルに書きたいと思います。/tmp/hi
$ $(echo "echo hi > /tmp/hi")
代わりに、ファイルと出力に何も書きません。
hi > /tmp/hi
ここで何が起こっているのでしょうか?最初は文字列にスペースがあるためだと思いましたが、次の内容はその理論を反証します。
$ $(echo "echo hi bob")
hi bob
答え1
bash
あなたの場合に適用されるマニュアルセクションは次のとおりです。
簡単なコマンド拡張
単純なコマンドを実行すると、シェルは左から右に次の拡張、割り当て、およびリダイレクトを実行します。
パーサーが変数の割り当て(コマンド名の前にある単語)とリダイレクトとして表示した単語は次のとおりです。後で処理するために保存。
変数の割り当てやリダイレクトではない単語は拡張されます。拡張後に残りの単語がある場合、最初の単語はコマンド名として扱われ、残りの単語は引数として扱われます。
リダイレクトは上記の「リダイレクト」の説明に従って行われます。
各変数の割り当てでは、=に続くテキストは、変数に割り当てられる前に、チルダ拡張、パラメータ拡張、コマンド置換、算術拡張、および引用符の削除を受けます。
コマンド$(echo "echo hi > /tmp/hi")
置換はポイント2で拡張され、>
ポイント1では後で処理するようにリダイレクトを表示できないため(コマンド置換の結果としてのみ表示されるため)、ポイント3では実行されません。
拡張する前にリダイレクトを前処理しない場合は、次のようになります。
to='>'; echo foo $to bar
そのままエコーされるのではなく、foo
ファイルにエコーされます。bar
foo > bar
bash
リダイレクト演算子次の単語に対しても分割+グロービングを行うという点で他のシェルとは異なります(複数の単語に展開されると「あいまいなリダイレクト」のため終了します)。たとえば、
var='a b'; echo > $var
他のシェルと同様に、名前付きbash
ファイルを破損するのではなくエラーが発生します。a b