次の形式のコマンドがあります。
input | tee >(subshell) | mainshell
サブシェルとメインシェルの両方が標準出力に書き込まれます。したがって、出力は同期されません。例えば
echo "Hello\nWorld" | tee >(grep -o ell | tr 'a-z' 'A-Z') | grep orld | sed 's/orl/ORL/g'
上記のコマンドが印刷されます。
ELL
WORLd
時々
WORLd
ELL
別の時間。
一時ファイル/名前が指定されたfifoを使用せずに予想される順序で行われていることを確認する簡単な方法はありますか?一部のファイル記述子リダイレクトを有効にすると役に立ちますか?
修正する:
順序は、メインシェルの出力、次にサブシェルの出力(またはその逆)を意味します。決定的であれば、必要に応じて変更できます。
これは、以下のようにfifoに名前を付けることで達成することもできます。
mkfifo f1 f2
echo "Hello\nWorld" | tee >(grep -o ell | tr 'a-z' 'A-Z' > f1) | grep orld | sed 's/orl/ORL/g' > f2 &
cat f1 f2
rm f1 f2
一時FIFOやファイルを避けることができるかどうかを知りたいです。
答え1
一時ファイル/名前が指定されたfifoを使用せずに予想される順序で行われていることを確認する簡単な方法はありますか?一部のファイル記述子リダイレクトを有効にすると役に立ちますか?
まさか。>(...)
そして...|...
いいえ境界保持 - 単一の書き込みがもう一方の端から複数の読み取りに変わらないという保証はありません(またはその逆)。
特定の順序を適用するには、アドバイザリロックを使用できます。参考flock(1)
そしてflock(2)
マンページ。これを達成する方法は、主にsubshell
プログラムの仕組みmainshell
によって異なります。非協力プログラムを盲目的にロックすると、簡単にデッドロックが発生する可能性があります(動作している場合)。
答え2
GNU Parallelは順序を変更せずに強制的に維持--tee
できます。--keep-order
ell() {
grep -o ell | tr 'a-z' 'A-Z'
}
orld() {
grep orld | sed 's/orl/ORL/g'
}
export -f ell
export -f orld
echo "Hello\nWorld" | parallel -k --tee --pipe ::: ell orld
しかし、背後でfifoと一時ファイルを使用します。しかし、問題を直接処理しないことが目標であれば、これが解決策になる可能性があります。
このソリューションはtmpfileを使用しますが、ほとんどすぐに切断されます。
myfunc1() { grep -o ell | tr 'a-z' 'A-Z'; }
myfunc2() { grep orld | sed 's/orl/ORL/g'; }
touch tmp1 tmp2
(
echo "Hello\nWorld" |
tee >( (rm tmp1; myfunc1) > tmp1 ) |
(rm tmp2; myfunc2) > tmp2
cat <&3
cat <&4
) 3< tmp1 4< tmp2
またはより短く:
(
rm tmp1 tmp2
echo "Hello\nWorld" |
tee >( grep -o ell | tr 'a-z' 'A-Z' >&5 ) |
grep orld | sed 's/orl/ORL/g' >&6
cat <&3
cat <&4
) 5> tmp1 6> tmp2 3< tmp1 4< tmp2