各行を前方に出力してから後方に出力するコマンド

各行を前方に出力してから後方に出力するコマンド

私は次のような「メタコマンド」xyzを探しています。

(echo "foo"; echo "bar") | xyz rev

次を返します。

foo oof
bar rab

一時ファイルを避けたい。つまり、次のようなよりきれいな解決策を探しています。

tempfile=$(mktemp)
cat > $tempfile
cat $tempfile | rev | paste $tempfile -

(もちろん、一般的な解決策が必要です。 だけでなく、すべてのコマンドに対して、revコマンドが各入力行に1行を出力すると仮定できます。)

Zshソリューションも許可されています。

ベストアンサー1

stdioバッファリングがどのように機能するかによって、ほとんどの場合、多くの問題が発生します。 Linuxの回避策は、このプログラムを使用stdbufしてcoprocを介してコマンドを実行して、出力のインターリーブを明示的に制御することです。

以下では、コマンドが各入力行の後に1行を出力すると仮定します。

#!/bin/bash
coproc stdbuf -i0 -o0 "$@"
IFS=
while read -r in ; do
    printf "%s " "$in"
    printf "%s\n" "$in" >&${COPROC[1]}
    read -r out <&${COPROC[0]}
    printf "%s\n" "$out"
done

OPはプログラムの各行への入力のみを必要とするため、より一般的な解決策が必要な場合最後にすぐに出力せずに1行ずつ出力するには、より洗練されたアプローチが必要です。標準入力と補助プロセスからデータを読み取ろうとするイベントループを作成し、両方がread -t 0同じ「行番号」を持っている場合は出力し、それ以外の場合は行を保存します。 CPUを100%使用したくない場合は、イベントループのどのラウンドでも準備ができていない場合は、イベントループを再実行する前に少し遅れてください。プロセスがバッファリングを必要とする部分ラインを出力する場合、追加の問題が発生します。

これにもっと一般的な解決策が必要な場合は、次のようにします。予想されるすでに複数の入力ストリームでパターンマッチングを処理するための優れたサポートを提供しているからです。しかし、これはbash / zshソリューションではありません。

おすすめ記事