2つのサブシェルがstdoutに書き込むときの出力のソート

2つのサブシェルがstdoutに書き込むときの出力のソート

次の形式のコマンドがあります。

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

関連情報