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

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

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

おすすめ記事