매우 큰 테이블이 있고 특정 행을 추출해야 합니다. 간단한 예를 들어 이 작업을 설명하겠습니다. 내가 사과, 바나나, 오렌지의 무게를 잰다고 가정해 보세요. 사과, 바나나, 오렌지의 최소 중량을 추출해야 합니다.
원본 테이블:
Apple 3
Banana 8
Orange 2
Apple 7
Banana 9
Orange 13
Apple 9
Banana 1
Orange 11
원하는 출력:
Apple 3
Banana 1
Orange 2
답변1
그리고gnu
datamash
:
datamash -s -g 1 min 2 <infile
아이폰 3 바나나 1 오렌지 2
이 작업은 st 필드를 기준으로 s
정렬 및 그룹화되어 첫 번째 필드의 각 ID에 대한 nd 필드의 값을 인쇄합니다. g
필드가 단일 탭 문자로 구분되어 있다고 가정합니다. 여러 공백으로 구분되거나 다른 필드 구분 기호(예: 단일 공백)를 정의하는 경우 다음을 사용하세요.1
min
2
-W, --whitespace
-t, --field-separator=
datamash -t' ' -s -g 1 min 2 <infile
입력을 정렬해야 하므로 datamash
출력도 첫 번째 필드를 기준으로 정렬됩니다.
답변2
그리고 awk
:
$ awk '($2<a[$1] || !a[$1]){a[$1]=$2}END{for(f in a){print f,a[f]}}' file
Orange 2
Banana 1
Apple 3
a[$1]=$2
a
키가 첫 번째 필드이고 값이 두 번째 필드인 배열을 설정합니다 . 위 스크립트는 i) 저장된 값보다 작거나 ii) 저장된 값이 없는 경우 두 번째 필드를 배열의 첫 번째 필드 값으로 저장합니다. 이 END
블록은 배열을 반복하고 해당 내용을 인쇄합니다.
GNU 사용 sort
:
$ sort -nk2 file | sort -u -k1,1
Apple 3
Banana 1
Orange 2
첫 번째 정렬은 가중치의 오름차순으로 행을 인쇄합니다(두 번째 필드). 두 번째 정렬은 고유한 행만 유지하고 첫 번째 필드만 확인합니다. 결과는 각 문자열의 첫 번째 항목을 인쇄하는 것이며, 첫 번째 정렬로 인해 해당 과일의 최소값이 됩니다.
Perl의 (약간) 더 짧은 버전도 있습니다:
$ perl -lane '$k{$F[0]}//=$F[1]; $k{$F[0]}=$F[1] if $F[1]<$k{$F[0]};
END{print "$_ $k{$_}" for keys(%k)}' file
Orange 2
Apple 3
Banana 1
//=
변수에 이미 값이 없으면 값이 할당됩니다. 그다음 방법은 awk
위와 동일합니다. 키가 과일이고 값이 가중치인 해시를 생성하고 %k
최소값을 저장합니다. 이 -a
플래그는 공백의 입력을 배열 로 분할하는 perl
것처럼 작동합니다.awk
@F
답변3
Perl oneliner를 사용하여 이 작업을 수행할 수 있습니다.
perl -ane '$h{$F[0]} = $F[1] if (!defined $h{$F[0]} || $h{$F[0]} > $F[1]);
END {foreach (keys %h) {print "$_ $h{$_}\n"}}' fruits_list.txt
여기서는 해시 맵(%h)을 사용하여 요소를 저장합니다. 과일이 해시에 아직 존재하지 않으면 첫 번째 값을 추가하고, 이미 존재하는 경우 이미 저장된 값보다 작은 경우에만 값을 업데이트합니다. END 블록은 파일의 마지막 줄을 처리한 후에만 실행되며 해시맵을 인쇄합니다.
답변4
sort -k2,2n file | sort -u -k1,1
산출:
아이폰 3 바나나 1 오렌지 2