여러 개의 중복 행이 있는 파일이 있는데 첫 번째 열만 다릅니다.
원본 파일:
2 A 3 rr 44 5 t y uuu 8
3 A 3 rr 44 5 t y uuu 8
0 B f 1
1 C 6 5 55 yy 7 4 3 4-5 tt efvho 44 3 5 gg 5 4 t rr 33
5 C 6 5 55 yy 7 4 3 4-5 tt efvho 44 3 5 gg 5 4 t rr 33
5 C 6 5 55 yy 7 4 3 4-5 tt efvho 44 3 5 gg 5 4 t rr 33
3 D tt v 44 f1 p
1 D tt v 44 f1 p
내가 원하는 것은 중복을 제거하고 첫 번째 열의 값을 합산하는 것입니다.
원하는 출력:
5 A 3 rr 44 5 t y uuu 8
0 B f 1
11 C 6 5 55 yy 7 4 3 4-5 tt efvho 44 3 5 gg 5 4 t rr 33
4 D tt v 44 f1 p
이 스크립트는 내가 하려는 작업과 매우 유사합니다.
awk '{a[$2]+=$1}END{for(i in a)print a[i] , i |"sort"}' file
다음과 같은 출력을 제공합니다.
5 A
0 B
11 C
4 D
이 스크립트의 첫 번째 열을 제외한 모든 열에 $2를 변경할 수 있는 방법이 있나요?
답변1
이것은 작동하지만 행의 순서를 유지하지 않습니다.
awk '{v=$1; $1=""; s[$0]=s[$0]+v} END {for (r in s) { printf "%s%s\n",s[r],r }}' file
- 첫 번째 필드를 변수에 저장한 다음 지웁니다.
- (비워진) 행이 있는 배열을
$1
키로 저장하고 저장된 합계를$1
값으로 저장합니다. - 마지막으로 배열을 인쇄합니다.
printf
삭제할 수 없고 비어 있을 뿐이므로 추가 공간을 피하기 위해 사용합니다$1
.
| sort -k2
두 번째 열을 정렬하려면 추가하세요 .
산출:
5 A 3 rr 44 5 t y uuu 8
0 B f 1
11 C 6 5 55 yy 7 4 3 4-5 tt efvho 44 3 5 gg 5 4 t rr 33
4 D tt v 44 f1 p
답변2
사용 datamash
및 awk
:
중복 행은 첫 번째 열에서만 다르기 때문에 이 datamash
명령이 작동합니다.
$ datamash -s -t' ' groupby 2 sum 1 --full <file |
awk '{$1=$NF; NF -= 1}1'
답변3
한 번에 한 라인만 메모리에 저장하고 awk를 사용하여 출력에서 입력 순서를 재현합니다.
$ cat tst.awk
{
currKey = $0
sub(/[^[:space:]]+ /,"",currKey)
}
currKey != prevKey {
if ( NR > 1 ) {
print prev0
}
prevKey = currKey
prev1 = 0
}
{
$1 += prev1
prev1 = $1
prev0 = $0
}
END {
print prev0
}
$ awk -f tst.awk file
5 A 3 rr 44 5 t y uuu 8
0 B f 1
11 C 6 5 55 yy 7 4 3 4-5 tt efvho 44 3 5 gg 5 4 t rr 33
4 D tt v 44 f1 p
위의 내용은 중복 행이 함께 그룹화되어 있다고 가정합니다. 그렇지 않은 경우 를 실행하십시오 sort -k2 file | awk '...'
.