특정 열에서 동일한 필드 값을 가진 행 그룹 정렬

특정 열에서 동일한 필드 값을 가진 행 그룹 정렬

다음과 같은 텍스트 파일이 있습니다.

1 bob A
1 jim B
1 Kate A
1 Nancy C
1 bill A
1 Jason A
2 James B
2 fill B
2 cake C
2 lucky C
2 Lucy A
2 lily B

각 그룹 1과 2의 데이터를 3열을 기준으로 정렬하려면 어떻게 해야 합니까? 출력은 다음과 같아야 합니다.

1 bob A
1 Kate A
1 bill A
1 Jason A
1 jim B
1 Nancy C
2 Lucy A
2 James B
2 fill B
2 lily B
2 cake C
2 lucky C

Kate입력 순서대로 표시되므로 출력 앞에 표시됩니다 .bill

열 1에는 1, 2부터 2000까지 매우 큰 값이 있으므로 행 수를 비교할 때 단순히 특정 값과 같을 뿐 아니라 awk print를 고려합니다.

답변1

sort파일은 첫 번째 열을 기준으로 숫자순으로, 세 번째 열을 기준으로 사전순으로 정렬됩니다.

sort -s -k1n,1 -k3,3 file

참고: -sPOSIX 사양의 확장입니다.

답변2

GNU 정렬이 있는 경우 -s다음을 참조하세요.@guest의 솔루션, 그렇지 않으면 cat+sort+cut을 사용하십시오.

$ cat -n file | sort -k2,2n -k4,4 -k1,1n | cut -f2-
1 bob A
1 Kate A
1 bill A
1 Jason A
1 jim B
1 Nancy C
2 Lucy A
2 James B
2 fill B
2 lily B
2 cake C
2 lucky C

답변3

배열의 각 행을 수집합니다. 줄의 첫 번째 단어가 이전 첫 번째 단어와 다른 경우 세 번째 단어로 정렬된 배열을 인쇄합니다. 간단한 일로 작업을 수행할 sort때 이는 약간 과잉일 수 있습니다 . 다음은 질문에 표시된 것과 다른 형식의 입력 파일을 고려하지 않습니다.

멍청하게:

BEGIN {ors=ORS; ORS=""; PROCINFO["sorted_in"]="@ind_str_asc"}

$1!=r {
    output()
    delete a
    r=$1
}
{
    a[$3]=a[$3] $0 ors
}

END {
    output()
}

function output() {
    for (i in a)
        print a[i]
}

파이썬:

import fileinput, operator
r=''; a=[]
def out():
    for p in sorted(a,key=operator.itemgetter(2)):
        print(' '.join(p))

for line in fileinput.input():
    x = line.rstrip().split()
    if r!=x[0]:
        r=x[0]
        if a:
            out()
            del a[:]
    a.append(x)
out()

진주:

perl -lae 'sub out {foreach(sort keys %a) {print $a{$_}}} BEGIN {$ors=$\;$\=""}
    if ($F[0] ne $r) {$r=$F[0]; out; %a=()}
    $a{$F[2]}=$a{$F[2]}.$_.$ors; END{out}'

답변4

이것이 awk당신이 원하는 솔루션입니다. (특히 gawk [GNU  awk]; POSIX에서는 작동하지 않습니다  awk.)

awk '
        function dump() {
                PROCINFO["sorted_in"] = "@ind_str_asc"
                for (arg3 in group) {
                        PROCINFO["sorted_in"] = "@ind_num_asc"
                        for (line_num in group[arg3]) {
                                print group[arg3][line_num]
                        }
                        PROCINFO["sorted_in"] = "@ind_str_asc"
                }
        }
        {
                if ($1 != saved_arg1) {
                        dump()
                        delete group
                        saved_arg1 = $1
                }
                group[$3][NR] = $0
        }
        END {
                dump()
        }
    '

주요 작업은 중간부터 시작됩니다. 각 행에 대해 해당 $1값이 가장 최근에 본 값과 다른 경우 새 그룹에 진입한다는 의미입니다. 이전 데이터 세트를 덤프하고(즉, 출력에 기록) 이전에 저장된 데이터 세트를 삭제하고 새 $1값을 기억합니다.

그런 다음 두 경우 모두 현재 행이 group배열에 추가됩니다. 이는 $3값과 NR (행 번호) 로 색인이 지정된 2차원 배열입니다 . 예를 들어, 예제 입력의 처음 6개 행에 대해 다음을 얻습니다.

group["A"][1] = "1 bob A"
group["B"][2] = "1 jim B"
group["A"][3] = "1 Kate A"
group["C"][4] = "1 Nancy C"
group["A"][5] = "1 bill A"
group["A"][6] = "1 Jason A"

7행에 $1 =가 표시되면 함수(프로그램 상단에 정의됨)를 2호출합니다 . , dump으로 for (arg3 in group)설정 arg3하세요 . 그런 다음 for  =  , 루프 (즉 , , 및 로  순차적 으로 설정됩니다 . 그래서 우리는 다음을 인쇄합니다.ABCarg3Afor (line_num in group[arg3])for (line_num in group["A"])line_num1356

1 bob A
1 Kate A
1 bill A
1 Jason A

다른 값은 이런 식으로 추론됩니다 $3. 다른 값은 이런 식으로 추론됩니다 $1.

관련 정보