두 개의 필드가 있는 큰 파일이 있습니다. 첫 번째 필드는 개체 이름을 나타내고 두 번째 필드는 해당 개체의 크기를 나타냅니다.
A 1
A 2
B 4
ABC 12
C 5
A 9
B 3
ABC 6
목록을 다음 형식으로 요약하고 싶습니다.
A 1,2,9
ABC 12,6
B 4,3
C 5
내가 생각해낸 해결책은 파일에 있는 고유한 개체 목록을 만들고 이를 반복하여 원본 파일과 일치시키는 것이었습니다.
for object in $(awk '{print $1}' objects_with_sizes.txt | sort -u);do
echo -n "$object "
awk -v pattern="$object" '$1==pattern{printf "%s%s" ,sep,$2;sep=","} END{print ""}' objects_with_sizes.txt
done
이 구현은 실행하는 데 오랜 시간이 걸립니다. 원하는 출력을 생성하는 더 효율적인 방법이 있습니까?
답변1
$ awk '{ object[$1]= (object[$1]==""?"":object[$1] ",") $2 }
END { for(obj in object) print obj, object[obj] }' infile
A 1,2,9
B 4,3
C 5
ABC 12,6
좀 더 효율적으로(메모리를 사용하며 메모리에 맞지 않는 대용량 파일에 중요함) awk 명령만 사용하여 위와 같이 파일 부분을 버퍼링하지 않고 객체 키가 변경될 때까지만 버퍼링하는 것입니다.
$ <infile sort -k1,1 -k2,2n |\
awk 'pre!=$1 { if(obj) { print obj; obj="" } }
{ obj= (obj==""?$1 " ":obj ",") $2; pre=$1 }
END{ if(obj) print obj }'
A 1,2,9
ABC 6,12
B 3,4
C 5
답변2
GNU 사용 datamash
:
$ datamash -t ' ' -s -g 1 collapse 2 <file
A 1,2,9
ABC 12,6
B 4,3
C 5
옵션:
-t '_'
필드 구분 기호로 공백 문자 사용-s
그룹화하기 전에 입력 정렬-g 1
첫 번째 필드의 그룹collapse 2
두 번째 필드의 값을 쉼표로 구분된 목록으로 축소합니다.
답변3
정렬한 다음 GNU sed에 입력하면 현재 첫 번째 필드를 이전 필드와 비교하여 해당 지점까지 쉼표로 구분된 OR을 인쇄합니다.
$ < file sort -s -k1,1 \
| sed -Ee '
:a
$!N
s/^((\S+)\s.*)\n\2\s+(\S+)/\1,\3/
ta
P;D
' -
A 1,2,9
ABC 12,6
B 4,3
C 5