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

디지털 파일의 내용은 과일과 동일하지만 첫 번째 및 두 번째 필드가 디지털 파일에 복사됩니다.

답변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당신은 이미 그 번호를 가지고 있지만 NR, printf그것을 사용하고 있지 않습니다 j.

답변3

나는 확실히 2002년에 SunOS nawk에 심각한 문제를 겪었습니다. 내 테스트 스크립트에 GNU가 아닌 awk에서 실행되는 세 가지 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

관련 정보