아래와 같은 파일이 있습니다. 점수 열을 기준으로 다음과 같이 전체 행을 출력하여 과목별 점수가 가장 높은 사람을 출력하고 싶습니다. 특정 순서는 필요하지 않지만 제목 열에는 모든 고유 항목이 포함되어야 합니다.
name subject score remarks
john Math 67 satis
lewis History 56 poor
sarah Math 89 good
fiona Geo 65 satis
george History 99 very good
원하는 출력:
name subject score remarks
sarah Math 89 good
george History 99 very good
fiona Geo 65 satis
모든 열은 탭으로 구분되며 메모 열에만 공백으로 구분된 단어가 있습니다. 동일한 과목에 대해 동일한 점수가 존재한다면, 모두 출력하고 싶습니다.
답변1
그것은 다음과 같습니다:
{
head -n 1 file.txt &&
tail -n+2 file.txt |
sort -t $'\t' -nrk 3 |
awk -F '\t' 's[$2] && s[$2] > $3 { next }{ s[$2] = $3 } 1'
} >outfile.txt
head -n1
제목을 인쇄하세요.tail -n+2
처리를 위해 헤더와 파이프라인의 나머지 부분을 건너뜁니다.sort
숫자를 역순으로 정렬합니다(높은 순서에서 낮은 순서로)(-rn
). 입력의 세 번째 열( )을 기준으로-k 3
정렬 하고 탭으로 구분합니다(-t $'\t'
이름이나 제목 열에 공백이 없는 경우 -를 제거할 수 있음).awk
제목이 보이지 않거나 마지막 줄과 같으면 해당 줄을 인쇄합니다.
-F '\t'
필드 구분 기호를 탭으로 설정합니다. 이름 및 제목 열에 공백이 없으면 제거할 수 있습니다.s[$2] && s[$2] > $3 { next }
다음;s[subject]
이 설정되어 있고 현재 값(최고 점수)보다 큰 경우입니다.{s[$2] = 1}
놓다s[subject] = score
1
인쇄
마지막 줄의 제목이 마음에 들지 않고 생각할 필요도 없다면이름또는주제공백 포함(예: 없음) - 다음과 같이 단축할 수 있습니다.
sort -nrk3 file.txt | awk ' s[$2] && s[$2] > $3{next}{s[$2]=$3}1'
답변2
awk 'BEGIN{ FS=OFS="\t" }
NR==1 { print; next }
max[$2]<$3 || NR==2{ max[$2]=$3; data[$2]=$0; next }
max[$2]==$3 { data[$2]= data[$2] ORS $0 }
END{ for(x in data) print data[x] }' infile
BEGIN{ FS=OFS="\t" }
, 탭\t
문자를 다음으로 설정하십시오.에프생산하다에스입력 구분 기호 및산소산출에프생산하다에스출력 구분 기호입니다.NR==1{ print; next }
, 제목 행을 출력합니다.max[$2]<$3 || NR==2{ max[$2]=$3; data[$2]=$0; next }
, 각 과목에 대해 가장 높은 점수를 업데이트 및 유지하고 해당 높은 점수 과목에 대한 전체 행을 유지합니다.max[$2]==$3{ data[$2]= data[$2] ORS $0 }
, 각 동일한 과목에 대해 동일한 최고 점수를 가진 레코드를 추가합니다.END{ for(x in data) print data[x] }
, 데이터 배열을 반복하고 최종 결과를 인쇄합니다.
답변3
GNU를 사용하여 각 주제의 첫 번째 항목만 sort
정렬하고 가져옵니다.uniq
sort -t '\t' -r -k 2 -k 3n scores.txt | uniq -f 1 -w 7
-k 2
주제별로(두 번째 필드) 정렬 -k 3n
n
하고 점수별로(세 번째 필드) 정렬합니다. 이 -r
옵션은 정렬 순서를 반대로 하여 점수가 가장 높은 항목이 먼저 표시됩니다.
이제 uniq
두 주제를 모두 제거하고 첫 번째 필드를 건너뛰고 -f 1
5개만 비교하므로 HistoryA
처음 5자를 공유하는 주제(예: and)에 대해서는 실패합니다 HistoryB
.
uniq
options 와 함께 명령을 사용하는 경우 -f
첫 번째 필드에는 공백이 포함되어서는 안 됩니다. 그렇지 않으면 필드가 공백이 아닌 문자가 이어지는 일련의 공백(일반적으로 공백 및/또는 탭)이기 때문에 잘못된 출력이 생성됩니다. 필드 구분 기호를 지정 하는 옵션은 특정 버전의 Debian에서만 uniq
사용할 수 있었지만 이제 호환성 이유로 제거되었습니다.-t
답변4
awk 'NR==FNR {if ($3>max[$2]) max[$2]=$3; next} FNR==1||$3==max[$2]' file file
입력 파일을 두 번 통과시킵니다. 가장 높은 점수는 첫 번째 패스에 기록되고 해당 행은 두 번째 패스에 인쇄됩니다. 점수가 0보다 크다고 가정합니다.