Linuxでawkスクリプトをソートする方法は?

Linuxでawkスクリプトをソートする方法は?

私のファイルにはfruit次の内容が含まれています。

Apples, 12
Pears, 50
Cheries, 7
Strawberries, 36
Oranges, 2

ファイルの数値データをソートしたいです。

for(i=1;i<=NF;i++)j+=$i;printf "Fruit %d%s, %d\n",NR,OFS,$1,j | sort -k 2 > "numbers"; j=0"

awkスクリプトを実行するには、次のコマンドを実行します。

awk -f numbers fruit

デジタルファイルの内容は果物と同じですが、最初と2番目のフィールドがデジタルファイルにコピーされます。

答え1

GNU awkは、配列のナビゲーション方法を制御するための賢い方法を提供します。配列巡回制御そして制御スキャン

gawk -F', ' '
    {fruit[$1] = $2}
    END {
        OFS = FS

        printf "\nordered by fruit name\n"
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (f in fruit) print f, fruit[f]

        printf "\nordered by number\n"
        PROCINFO["sorted_in"] = "@val_num_desc"
        for (f in fruit) print f, fruit[f]
    }
' fruit

出力

ordered by fruit name
Apples, 12
Cheries, 7
Oranges, 2
Pears, 50
Strawberries, 36

ordered by number
Pears, 50
Strawberries, 36
Apples, 12
Cheries, 7
Oranges, 2

答え2

print実際にawkを渡すことができます"sort"(引用符を参照)。

$ awk '{print "Fruit",NR, $0 | "sort -k 2 -t, -rn"}' fruit 
Fruit 2 Pears, 50
Fruit 4 Strawberries, 36
Fruit 1 Apples, 12
Fruit 3 Cheries, 7
Fruit 5 Oranges, 2

したがって、に書き込むにはnumbers

awk '{print "Fruit",NR, $0 | "sort -k 2 -t, -rn > numbers"}' fruit 

私はあなたのawkを少し単純化しました。どこでも変更できないため、printfここで明示的に使用したり印刷したりする必要はありません。私もあなたが何をしているのかOFS理解できません。for(i=1;i<=NF;i++)j+=$iあなたはすでにその番号を持っていますがNRprintfそれを使用していませんj

答え3

私は確かに2002年にSunOS nawkに深刻な問題を経験しました。私のテストスクリプトには、GNUではなくawkで実行される3つのawk実装が含まれていることがわかりました。

(a)eSort:作業ファイルを使用し、ソートコマンドを実行するパイプラインを介して再読み込みします。私の場合は、SSHを介してエージェントレス監視を実行しており、外部作業ファイルがライブサーバーに干渉しすぎるため、状況は悪くなります。

(b) qSort: 再帰的なパーティションのソート。ビッグデータの場合、パフォーマンスが悪く、2000以上の要素がmawkのスタックを破損します。でも書いて楽しかったです。

(c)hSort:15行の内部整列アルゴリズム。ヒープはインデックスアルゴリズムを使用してバイナリツリーをサポートします(Wikipediaを参照)。

このbashスクリプトには、実際のソートを実装するawk関数hSortとhUpが含まれています。アクションラインはすべての入力を配列に入れ、ENDブロックはhSortを呼び出して結果を報告します。

入力データは「man bash」の内容で、一度は行、一度は単語です。何も失われなかったことを証明するためにwcを使用し、出力がソートされたことを証明するためにsort -cを使用します。タイミングには読み取りと印刷のオーバーヘッドが含まれます。

テストショットは次のとおりです。

Paul--) ./hSort

Sorted 5251 elements.

real    0m0.120s
user    0m0.116s
sys     0m0.004s
  5251  44463 273728 hSort.raw
sort: hSort.raw:2: disorder: 
  5251  44463 273728 hSort.srt

Sorted 44463 elements.

real    0m1.336s
user    0m1.316s
sys     0m0.008s
 44463  44463 265333 hSort.raw
sort: hSort.raw:3: disorder: Commands
 44463  44463 265333 hSort.srt

これがスクリプトです。楽しむ!

#! /bin/bash

export LC_ALL="C"

#### Heapsort algorithm.

function hSort {    #:: (void) < text

    local AWK='''
#.. Construct the heap, then unfold it.
function hSort (A, Local, n, j, e) {
    for (j in A) ++n;
    for (j = int (n / 2); j > 0; --j) hUp( j, A[j], n, A);
    for (j = n; j > 1; --j) { e = A[j]; A[j] = A[1]; hUp( 1, e, j - 1, A); }
    return (0 + n);
}
#.. Given an empty slot and its contents, pull any bigger elements up the tree.
function hUp (j, e, n, V, Local, k) {
    while ((k = j + j) <= n) {
        if (k + 1 <= n  &&  STX V[k] < STX V[k + 1]) ++k;
        if (STX e >= STX V[k]) break;
        V[j] = V[k]; j = k;
    }
    V[j] = e;
}
{ U[++nU] = $0; }
END {
    sz = hSort( U);
    printf ("\nSorted %s elements.\n", sz) | "cat 1>&2";
    for (k = 1; k in U; ++k) print U[k];
}
'''
    mawk -f <( printf '%s\n' "${AWK}" )
}

#### Test Package Starts Here.

function Test {
    time hSort < hSort.raw > hSort.srt
    for fn in hSort.{raw,srt}; do wc "${fn}"; LC_ALL="C" sort -c "${fn}"; done
}
    AWK_LINE='{ sub (/^[ \011]+/, ""); print; }'
    AWK_WORD='{ for (f = 1; f <= NF; ++f) print $(f); }'

    #xxx : > hSort.raw; Test        #.. Edge cases.
    #xxx echo "Hello" > hSort.raw; Test
    #xxx { echo "World"; echo "Hello"; } > hSort.raw; Test

    man bash | col -b | mawk "${AWK_LINE}" > hSort.raw; Test
    man bash | col -b | mawk "${AWK_WORD}" > hSort.raw; Test

関連情報