다음과 같은 형식을 취하려고 합니다.
a b hello
a b goodbye
g g test
a c I say
열 3의 정보를 잃지 않고 열 1과 2의 각 고유 항목에 대해 테이블을 하나의 행으로 축소합니다. 3열의 값은 쉼표로 구분된 목록으로 추가될 수 있습니다. 결과는 다음과 같습니다.
a b hello, goodbye
a c I say
g g test
어디서부터 시작해야할지 모르겠습니다. 을 사용하면 sort -k1,1 -k2,2 -u
다음과 같은 결과를 얻습니다.
a b hello
a c I say
g g test
"Goodbye" 항목을 잃어버렸는데 보관하고 싶습니다. 위의 예에 표시된 것처럼 3열의 데이터를 삭제하지 않는 방법을 아는 사람이 있나요?
답변1
독립형 방법은 모르지만 sort
awk를 사용하여 값을 "축소"한 다음 정렬할 수 있습니다.
$ awk -F'\t' '
BEGIN{OFS=FS}
{k = $1 FS $2}
{a[k] = a[k] == "" ? $3 : a[k] "," $3}
END{for (k in a) print k,a[k]}
' file | sort
a b hello,goodbye
a c I say
g g test
최신 버전의 GNU awk에서는 다음을 설정하여 외부 정렬을 피하기 위해 배열 순회 순서를 설정할 수 있습니다 PROCINFO
.
awk -F'\t' '
BEGIN{OFS=FS}
{k = $1 FS $2}
{a[k] = a[k] == "" ? $3 : a[k] "," $3}
END{PROCINFO["sorted_in"]="@ind_str_asc"; for (k in a) print k,a[k]}
' file
또는 GNU datamash를 사용하십시오.
datamash groupby 1,2 collapse 3 <file
또는 더 자세한 (그러나 더 유연한) Miller
mlr --nidx --fs tab nest --implode --values --across-records --nested-fs , -f 3 file
답변2
Bash에서 임시 파일을 사용하는 2단계 솔루션:
$ cat table.csv
a b hello
a b goodbye
g g test
a c I say
$ WD=$(mktemp -d) ; while read K1 K2 V ; do echo -n ",$V" >>$WD/$K1:$K2 ; done <table.csv
$ sort -k1,1 -k2,2 -u table.csv | while read K1 K2 V ; do echo $K1 $K2 $(sed 's/^.//' <$WD/$K1:$K2) ; done
a b hello,goodbye
a c I say
g g test
해결 방법의 요점은 >>
정렬하기 전에 동일한 키에 대한 값을 수집하기 위해 Shell Append Redirect()를 사용하는 것입니다.
답변3
함수를 사용하여 수행할 수도 있습니다 sed
(죄송하지만 사람이 실제로 읽을 수는 없습니다).
echo "a b hello
a c goodbye
g g foo
a c bar
a b test
a c I say" | sort -k1,1 -k2,2 | sed ":a N; s/\([^\t]*\)\t\([^\t]*\)\t\([^\t]*\)\n\1\t\2\t\([^\t]*\)/\1\t\2\t\3,\4/; ta; P; D; ba;"
출력은 예상대로입니다.
a b hello,test
a c bar,goodbye,I say
g g foo
- 먼저 정렬한 다음
sed
교체를 사용하세요uniq
. N;
sed
1개 행 대신 2개 행(또는 "1개 추가 행")을 처리 해야 합니다 .s/.../.../
두 줄을 병합합니다.\([^\t]*\)
하나의 열을 차지합니다(스트립 없이 가능한 한 많은 문자\t
).\t
탭 문자(구분자)입니다.\n\t\1\t\2\t
두 번째 행에 두 개의 유사한 첫 번째 열이 있는지 확인하세요./\1\t\2\t\3,\4/
2개의 행을 첫 번째와 두 번째 열이 동일한 하나의 행으로 변환하고 세 번째 열을 병합합니다.
:a ... ta;
루프 와 같습니다while
( work 교체 시 다시 실행됨s
).P; D;
여기에 있으면s
실패하므로 패턴 공간에 두 개의 "다른"(첫 번째 또는 두 번째 열에) 줄이 있습니다.P
첫 번째 줄(병합된 줄이 포함될 수 있음)을 인쇄하고D
인쇄한 줄을 제거합니다.ba;
행을 읽을 수 있는 동안 반복합니다(현재 패턴 공간에는 1개의 행이 있습니다).