手続き型置換の出力を変数としてパイプ

手続き型置換の出力を変数としてパイプ

非常に複雑な命令セットがあります。

command | ... | ... | tee >(grep -c '[^3]$') >(grep -c '[^35]$') 1>/dev/null

出力が非常に大きいため、出力を保存するための一時ファイルを使用したくありません。私は>(grep -c '[^3]$' | read variable)これを試しましたが、>(grep -c '[^3]$' | read variable2)プロセスの置き換えのためにサブシェルビットが機能しないようです。

出力を複数の変数に直接パイプするにはどうすればよいですか?可能ですか?

今、次の回避策があります。

var=$(command ... | ... | ... | tee >(grep -c '[^3]$') >(grep -c '[^35]$') 1>/dev/null)
var1=$(tail -1 <<< $var)
var2=$(head -1 <<< $var)

でも、私の考えには這い、見に良くないと思います。私は他のファイルをgrepできることを知っていますが、それも好きではありません。

よろしくお願いします。

答え1

両方のgrepプロセスを置き換えるには、-ingawkの代わりに使用します。teeたとえば、

command | ... | ... | awk '
     /[^3]$/  { c1++; next };
     /[^35]$/ { c2++; next };
     END { print c1, c2 > counts.txt }'

read var1 var2 < counts.txt
rm counts.txt

一時ファイルを使用したくない場合は、次のようにします。

read var1 var2 < <(command | ... | ... | awk '
         /[^3]$/  { c1++; next };
         /[^35]$/ { c2++; next };
         END { print c1, c2 }')

答え2

まず、コマンドチェーンからstdoutを送信するため、割り当て/dev/nullにNULL値を割り当てることができます。削除してください。出力の最初の行と最後の行だけをキャプチャしようとしているようです。 1行で処理するのは難しいかもしれませんが、awk次のように処理できます。

var="$(command ... | [...] | tee [...] | awk 'NR==1{print $0} END { print $0}')"

しかし、パイプは単純な生き物です。入力と出力があります。パイプを(簡単に)使用して複数の場所にデータを送信することはできません。あなたが得ることができる最も近いものは使用することです名前付きパイプは本質的に回避しようとする一時ファイルです(技術的に正しくありません。FIFOキューはファイルと同じではありませんが、単純化しています)。

関連情報