このスクリプトの蓄積的なコピーがあります。
#!/usr/bin/env bash
handle_json(){
while read line; do
cat <<EOF
{"@json-stdio":true,"value":{"mark":"$1","v":"$line"}}
EOF
done;
}
( echo; echo; echo 'du results:'; exit 0 ) > >(handle_json foo);
echo "zoom"
実行すると、次の結果が表示されます。
それ自体が終了しないため、ctrl-Cを使用して手動で終了する必要があります。
私が望むのは、サブシェルの標準出力をbash関数に送信してJSONに出力を文字列化させることです(今は特殊文字エスケープを心配する必要はありません)。
このスクリプトがそれ自体で終了しない理由を知っている人はいますか?
修正する:
これは実際に私が望むことを行います。
( echo; echo; echo 'du results'; ) | handle_json 'foo';
echo "zoom"
上記は、リダイレクト/プロセス置換の代わりにパイプ演算子を使用します。パイプラインオペレータがここで働くとは予想していませんでした。誰がなぜ/どのように動作するのか説明できますか?
答え1
私が知る限り、あなたのスクリプトはした終了します。シェルがプロンプトを印刷した直後、プロセスの交換はバックグラウンドで実行および印刷を完了します。
これを回避する1つの方法は、次を使用する代わりに関数をパイプすることです> >(...)
。
( echo; echo; echo 'du results:'; exit 0 ) | handle_json foo
これは、書き込み時に標準出力が標準入力に接続されているcmd1 | cmd2
間に2つのコマンドが並列に実行されるために機能します。cmd1
cmd2
そしてbashは、パイプラインが完了したと見なされる前に両方が完了するのを待ちます。
比較すると、cmd1 > >(cmd2)
bashが追加のコマンドを続行する前に完了するのを待たないことを除いて、ほぼ同じですcmd2
(この場合は「zoom」を印刷してから終了し、対話型bashがプロンプトを印刷できるようにします)cmd2
。それよりはるかに多くの時間がcmd1
かかると、あなたが観察した驚くべき競争状況が発生します。