Linux에서 두 행마다 값을 합산하는 방법

Linux에서 두 행마다 값을 합산하는 방법

다음과 같은 데이터가 있습니다.

입력.txt

1 0000100101000000
1 0000010100000000
2 1110000001000000
2 1111000000001000
3 0000000111111111
3 1111111100000000
4 8888345500000000
4 0000000000000000

동일한 행 번호를 가진 두 행마다 값을 합산하고 싶습니다. 출력:

출력.txt

1 0000110201000000
2 2221000001001000
3 1111111211111111
4 8888345500000000

어떤 제안이 있으십니까? 내 실제 데이터에는 각 행에 45000개의 숫자가 있는 8000개의 행이 있습니다.

답변1

전반적인 awk솔루션은 어떻습니까?

awk 'BEGIN { tag = -1; sum = 0}
    {
        if (tag != $1) {
            if (tag > -1) {printf "%d %016d\n",  tag, sum;}
            tag = $1; sum = $2
        } else { sum += $2 }
    }
    END {print tag, sum}'  input.txt

입력이 첫 번째 열을 기준으로 정렬되었는지 확실하지 않습니다. 다음을 수행할 수 있습니다. 그런 다음 이를 위의 스크립트 sort -k1.1n input.txt에 파이프합니다 .awk

답변2

sed '
    N                                                       #append next line
    s/$/))/                                                 #add `))` to end
    s/\(\S*\s*\)\(.*\)\n\1/printf "%016d\n" \$((10#\2+10#/  #check Nos, form line
    t                                                       #to end if Nos equal
    s/))$//                                                 #remove `))`
    D                                                       #delete 1st line
    ' file |
bash

45000 자리 숫자와 관련하여 bash가 처리할 수 있는 가장 큰 숫자는 다음과 같습니다.

/* Minimum and maximum values a `signed long int' can hold.  */
#  if __WORDSIZE == 64
#   define LONG_MAX 9223372036854775807L
#  else
#   define LONG_MAX 2147483647L
#  endif

[1]/usr/include/limits.h

답변3

Ruby는 bignum을 지원하므로 다음을 수행할 수 있습니다.

ruby -e '
    sum = Hash.new {|h,k| h[k] = 0} 
    f = File.new(ARGV.shift)
    key, val = f.readline.chomp.split
    width = val.length
    sum[key] = val.to_i
    f.each_line {|line| key,val = line.chomp.split; sum[key] += val.to_i}
    sum.keys.sort.each {|key| printf "%d %0*d\n", key, width, sum[key]}
' file

답변4

추가할 행이 항상 2개 있고(3개나 1개 등이 아님) 숫자가 항상 두 번째 열에 공백으로 구분되어 있다고 가정할 수 있다면 간단한 해결책이 있습니다.

cut -f2 -d' ' input.txt | perl -Mbigint -nle 'print $_ + <>' > output.txt

cut명령은 데이터의 두 번째 열만 선택하고 첫 번째 열은 삭제합니다. 이 perl명령은 (스위치를 사용하여) 전달된 줄을 반복 -n하고 현재 줄과 다음 줄의 합계를 인쇄합니다(그래서 두 세트로 작동합니다). 이 bigint모듈을 사용하면 긴 문자열을 매우 큰 숫자로 처리한다는 점에 유의하세요 . 마지막으로 출력이 로 리디렉션됩니다 output.txt.

출력에 번호가 매겨진 줄이 필요한 경우 이를 cat -n파이프라인의 마지막 단계로 추가하거나 Perl 코드에 추가하는 것을 고려할 수 있습니다.

cut -f2 -d' ' input.txt | perl -Mbigint -nle 'print ++$x . " " . ($_ + <>)' > output.txt

또는 예제에서처럼 입력 형식이 공백이라고 가정할 수 없는 경우 해당 처리를 Perl로 이동할 수도 있습니다.

perl -Mbigint -nle 's/.* //; $x=<>; $x =~ s/.* //; print $_ + $x' input.txt > output.txt

관련 정보