다음과 같은 텍스트 파일이 있습니다.
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
참고: -s
POSIX 사양의 확장입니다.
답변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 = , 루프 (즉 , , 및 로 순차적 으로 설정됩니다 . 그래서 우리는 다음을 인쇄합니다.A
B
C
arg3
A
for (line_num in group[arg3])
for (line_num in group["A"])
line_num
1
3
5
6
1 bob A
1 Kate A
1 bill A
1 Jason A
다른 값은 이런 식으로 추론됩니다 $3
. 다른 값은 이런 식으로 추론됩니다 $1
.