bashのマンページによると、「リダイレクト演算子は、単純なコマンドの前またはコマンド内のどこにでも表示できます。
また、マニュアルページによると、「単純なコマンドは、一連のオプションの変数割り当て、スペースで区切られた単語、およびリダイレクトが続き、制御演算子によって終了されることです」
今質問があります。単純なコマンドとシェルが意味するコマンドは何ですか?なぜなら、/bin/echo foo {var}> somefile
varにfdが割り当てられていないからです。対照的に、これecho foo {var}> somefile
により fd が var に割り当てられます。命令とは異なり、組み込みの命令で動作するようです。私はこの構造が組み込みコマンドが使用されるどこにでも現れることがわかりました{var}> someFile echo foo
。この場合、単純な命令が組み込み命令で構成されている場合、単語やトークンも組み込み命令ですか?マニュアルページに次のように記載されているからです。 「Word: シェルで単一単位で処理される一連の文字です。トークンとも呼ばれます。」
また、外部コマンドの代わりに組み込みコマンドと一緒に使用した場合、fdが割り当てられることも観察しました。それでは、ここで問題は何ですか?私の観察は正しいですか?単純なコマンドとコマンドの違いは何ですか?マンページはこれについて非常にあいまいです。
答え1
私の頭の上では、これは外部コマンドを実行するとシェルが1)フォーク、2)サブプロセスのリダイレクトを処理し、3)execが実際のコマンドであるためと推測します。 2で割り当てが完了すると、子var
プロセスで開始されたプログラムが終了した後に親シェルに表示されません。組み込み機能を使用するとフォークがなくなり、シェルは基本的なシェルプロセスで必要に応じてfdを処理し、そこから変数の割り当てが適用されます。
とにかくリダイレクトはsome external command {var}>/whatever
役に立たないので重要ではありません。外部コマンドは、どのfdが開いているのかわからず、どのfdがあるかを確認できますが、この行のリダイレクト用に開かれている以外に他のfdがある可能性があるため、そのfdを確実に使用することはできません。に出力します/whatever
。代わりに、通常は固定のfd番号を使用するか、いくつかのコマンドライン引数または環境変数を使用して使用するfd番号を指定します。
しかし、ここでもそうすることはできません。これは、コマンドラインで拡張を処理するときに変数が設定されていないため、実行されたプログラムに渡すのが難しいからです。unset var; /bin/echo "var=$var" {var}>/dev/null
出力はまさにそれvar=
ですunset var; var=$var /usr/bin/env {var}>/dev/null |grep ^var
。 (kshとzshでは、後者は環境を通して実際の数を渡すようです。)
このリダイレクトが意味を持つ唯一の場所は、組み込みexec {var}>/whatever
変数として変数がデフォルトのシェルに設定され、値が次のコマンドで使用可能な場合です。
答え2
GNU bashドキュメントセクション3.6段落2には「リダイレクトするたびに…」と示されています。
fdのようなコマンドでfdが実際に使用されているかどうかにかかわらず、すべての組み込みcmd {fd}>file
コマンドはfdを設定するように見え、外部コマンドはfdを設定しないようです。 bashまたはガイドが間違っています。
Paul--) echo "Hello, Worms" {var}>real 1>&${var}
Paul--) declare -p var; ls -l real; cat real
declare -- var="11"
-rw-r--r-- 1 paul paul 13 Sep 2 10:27 real
Hello, Worms
Paul--)
Paul--) /bin/echo "So long, suckers" {why}>deal 1>&${why}
Paul--) declare -p why; ls -l deal; cat deal
bash: declare: why: not found
-rw-r--r-- 1 paul paul 17 Sep 2 10:29 deal
So long, suckers
Paul--)
実際、$why値は2番目のリダイレクト(stdout)で使用できますが、ガイドで指定されているものとは異なります。 {varname} が指定された場合、リダイレクトは続行されます。コマンドの範囲を超えて...」。
この割り当ての唯一の利点は、エンコーダが番号を追跡する必要がなく、名前で利用可能なfdを割り当てることです。
: 9>myFirstFile
cmd >&9
: {fdLog}>myLogFile
cmd >&${fdLog}