標準入力の行グループへのコマンドの適用

標準入力の行グループへのコマンドの適用

Unixパッケージdatamashマルチアグリゲーションタスクをサポートするアプリケーショングループ行数を入力してください。たとえば、1は、次のように、datamash列1の各値の列2の合計を計算するために使用されます。

$ cat example.csv
1,10
1,5
2,9
2,11
$ datamash -t, -g 1 sum 2 < example.csv
1,15
2,20

サポートされている機能datamashも非常に広いですが、(、、、、などをsum含む)拡張できません。 AFAICT。 IOWでは、ユーザーが自分の要約機能を提供できるメカニズムはサポートされていません。meanstddevmedianiqrminmaxdatamash

私の質問は次のとおりです。一般に、zsh2でこの種のコマンド固有のグループアプリケーションをどのように実装できますか?


以下では、問題をより正確に説明したいと思います。 (正確な試みで質問が理解できなくなることを願っています。)

まず、fooこれが次の構造を使用してstdoutラインに送信された(複合可能)コマンドを表すとします。

仕切り ペイロードi j

...どこ、「グループインデックス」は整数です。仕切り定数区切り文字シーケンス(たとえば、、,または$'\t')。ペイロードi j任意のテキストです(終了文字を含む)。また、グループインデックスを想定すると範囲は1から窒素、この出力の行はグループインデックスに従ってソートされます。

すべての整数に対して1≤ K ≤ 窒素、許す」K「グループ-」は、フラグメントで構成されるコンテンツを示す。ペイロードkjfooグループインデックスを持つすべての行(の出力)K

次に、これがbarstdinで行を読み取って発行する(複合でもよい)コマンドを表すとします。一つの線標準出力として。

結果Kbar次に適用される出力を示します。K- 番目のグループ、X<bar>呼び出すシェル構成を表現してみましょうbar

私は基本的にX<bar>パイプを作る構造を探しています。

foo | X<bar>

フォームのstdout行に送信されます。

仕切り 結果


編集する:

仮説仕切りもしそうなら,、以下は私の要件を満たすようです。

TMPFILE=$( mktemp )
SEPARATOR=,
LASTGROUPID=
foo | (cat; echo) | while IFS= read -r LINE
do
    GROUPID=${LINE%%$SEPARATOR*}
    if [[ $GROUPID != $LASTGROUPID ]]
    then
        if [[ -n $LASTGROUPID ]]
        then
            echo -n "$LASTGROUPID$SEPARATOR"
            cat $TMPFILE | bar
        fi
        LASTGROUPID=$GROUPID
        : > $TMPFILE
    fi
    PAYLOAD=${LINE#*$SEPARATOR}
    echo $PAYLOAD >> $TMPFILE
done
rm $TMPFILE

$TMPFILEデフォルトでは、これは次のグループの行を収集するために使用されます。 (一時ファイルは避けたいのですが、どうすればいいのかわかりません。)

barここで、表現された式をパラメータとして使用し、上記の構文でそれを強く使用できる関数として実装する方法を見つける必要があります。


1このdatamash例は、マニュアルページで提供されている例を修正したものです。

2私は主な関心がありますが、副次的な関心もありますzshbash

答え1

私にとって、これはシェル操作のようには見えません。私はこれを行いますperl...ここで十分かもしれませんが:pythonrubyawk

$ cat sum
paste -sd + - | bc
$ sort -t , -k 1,1 input | awk -F, -v cmd=./sum '
   function out() {printf "%s,", l;close(cmd)}
   NR>1 && $1 != l {out()}
   {print $2 | cmd; l=$1}
   END {if (NR) out()}'
1,15
2,20

答え2

あなたが探しているものが何であるかを知っている場合は、サンプルセットから分布を生成するのと似ていますが、より多くの累積オプションがあるスクリプトです。私はawkこれのためにスクリプトを書いた。

https://drive.google.com/open?id=0B0Kg_QLltwbNU21zbHFMY1hnSjQ

これはまさに望むものではありませんが、重なり合う部分が大きくなければなりません。最初 - インデックスは整数であるだけでなく、2番目 - 唯一の累積方法は合計です。しかし、単純なスクリプトなので、Cプログラムよりも簡単に修正できます。

最後に、これらのスクリプトはデータセットが十分に小さい場合にのみ機能し、より大きなデータセットの場合は遅すぎます。したがって、より専門的なパッケージがより良い(Rなど)。

PS追加アキュムレータを追加するには、カスタム+=関数(「monad」)で置き換えます。

関連情報