Unix에는 스트림에서 관계 대수와 유사한 작업을 수행하기 위한 여러 유틸리티가 있습니다( grep
, join
, , , cut
에 추가 awk
). 즉시 사용 가능한(또는 대부분의 Linux 배포판에 설치 가능한) 그룹 집계 유틸리티가 있습니까?
목표는 다음과 같이 한 열에 일부 키가 있고 다른 열에 일부 값이 있는 파일을 얻는 것입니다.
foo.txt u1 394082
bar.txt u2 3948
frob.c u1 29322
그리고 한 열에는 고유한 값이 있고 다른 열에는 일부 값의 집합이 있는 파일을 출력합니다. 예를 들어 세 번째 열과 두 번째 열의 합계는 다음과 같습니다.
$ aggregate --sum=3 --group-by=2 <data
u1 423404
u2 3948
그러한 유틸리티가 존재합니까(Perl, Awk 등, 한 줄은 포함되지 않음), 아니면 아직 작성되지 않았습니까?
답변1
다른 StackOverflow 질문에서 이 답변을 찾은 것 같지만 "q"가 이 목적에 매우 유용하다는 것을 알았습니다.https://github.com/harelba/q.
예를 들어 샘플 목표는 다음과 같이 달성될 수 있습니다.
$ q "select c2, sum(c3) from data group by c2"
u1 423404
u2 3948
sqlite를 백엔드로 사용하기 때문에 다양한 sqlite 함수를 사용하여 계산할 수 있습니다.
답변2
몇 가지 제한사항이 있습니다.GNU Recutils이것은 가능합니다. 먼저 TSV가 아닌 CSV 파일이어야 하며(Recutils는 TSV 파일을 좋아하지 않는 것 같습니다) 헤더가 필요합니다. 하지만 나는 이렇게 할 수 있다:
csv2rec foo.csv |recsel -G user -p 'user,sum(size)' |rec2csv
이것이 Perl이나 Awk one-liner보다 나은지 나쁜지 확실하지 않습니다.
답변3
awk 한 줄짜리가 포함되지 않는다면 아마도 다음 쉘(bash/ksh) 한 줄짜리를 원할 것입니다:
sort -k2 data | ( while read c1 c2 c3; do if [ "$prev" = "$c2" ]; then
sum=$(expr $c3 + $sum); else if [ $prev ]; then echo $prev $sum; fi;
sum=$c3; prev=$c2; fi; done; echo $prev $sum)
그리고 (각각 그룹화 및 합산을 위해) 여기에 사용된 흥미로운 요소 sort
는 expr
while 내부의 읽기 문입니다. 괄호는 지역화 $prev
및 변수 $sum
에 필요한 하위 프로세스를 만듭니다 .