cmd_drain <<<(cmd_src)とcmd_drain <<<"$(cmd_src)"の違いはありますか?

cmd_drain <<<(cmd_src)とcmd_drain <<<"$(cmd_src)"の違いはありますか?

私たちが知っているように、このcmd | read -r var1 var2設定はパイプのために読み取りコマンドがサブシェルで実行されるため、bashでは機能しません。私はこの問題を解決しましたが、read -r var1 var2 <<< "$(cmd)"最近この構造について知りましたが、cmd_drain < <(cmd_src)それはうまくいくようですread -r var1 var2 < <$(cmd)

これら2つのソリューションの間に違いはありますか?いいえ〜らしいマイナーな違いがある場合:

$ hd < <(echo Hello)
00000000  48 65 6c 6c 6f 0a                                 |Hello.|
00000006
$ hd <<< $(echo Hello)
00000000  48 65 6c 6c 6f 0a                                 |Hello.|
00000006

また、いくつかの特殊文字を試しましたが、同じ結果を得ました。私の直観によると、結果は常に同じです。cmd_drain <<< "$(cmd_src)"最初に実行しcmd_src、結果全体をメモリにバッファリングしてから供給しますが、出力cmd_draincmd_drain < <(cmd_src)連続してcmd_src供給されますcmd_drain。 NETの代わりにサブシェルで実行されているcmd_src | cmd_drainことを除いて、以前と同じように機能すると仮定します。私の仮定は正しいですか?cmd_srccmd_drain

ボーナスの質問:構造体の周りに参照が必要ですか$()

答え1

はい、あなたの家は正しいです。cmd_drain < <(cmd_src)(別名。プロセスの交換、通常のリダイレクトと組み合わせる)Bashはそれを出力を読み取ることができる<(cmd_src)ファイルへのパスに置き換えます。cmd_srcドキュメントから:

プロセスのリストは非同期で実行され、対応する入力または出力はファイル名で表示されます。ファイル名は拡張の結果として現在のコマンドに引数として渡されます。フォームを使用している場合は、>(list)ファイルに書き込むとリストへの入力が提供されます。この形式を使用する場合は、 <(list)引数として渡されたファイルを読み取ってリストの出力を取得する必要があります。

では他と同様に処理されますcmd_drain <<< "$(cmd_src)"<<< ...ここにある文字列だから:

単語には、チルダ拡張、パラメータおよび変数拡張、コマンド置換、算術拡張、および引用符の削除があります。パス名の拡張とトークン化は行われません。結果は、改行文字[...]が追加された単一の文字列として標準入力のコマンドに提供されます。

したがって、そこに引用する必要はありませんが、$()特にここの文字列構文は<<<トークン化やファイル名拡張を行わないので、さらにそうです。通常、これを行う必要があります。


ここで文字列文書の最後の文をもう一度参照してください。改行文字が追加されます。

bash-5.0$ od -c <<< $(printf %s foo)
0000000   f   o   o  \n
0000004
bash-5.0$ od -c < <(printf %s foo)
0000000   f   o   o
0000003

これが重要かどうかは、実行中の項目によって異なります。

からhd <<< $(echo Hello)置換コマンドは、出力から末尾の改行文字を削除し、文字列にecho改行文字が追加され、実質的に同じ出力を提供します。ただし、上記の例に示すように、改行を削除/追加するのは難しいかもしれませんcmd_src

関連情報