sed 또는 nawk를 사용하여 열의 대체 값 합계 계산

sed 또는 nawk를 사용하여 열의 대체 값 합계 계산

foo.txt:

1  10     11
2   20     22
3   30     32
4   40     42
5   50     52
6   60     62
7   70     72
8   80     82
9   90     92
10  100   110

예상하다 Out.txt:

1  10     11
2   20     22
3   30     32
4   40     42
5   50     52
6   60     62
7   70     72
8   80     82
9   90     92
10  100   110
25  250   275   #Line 11
30  300   330   #Line 12
45  550   595  #Line 13

11행은 1행에서 시작하여 1, 2, 3열의 교대 행의 합이고, 12행은 2행 합계에서 시작하는 1, 2, 3열의 교대 행의 합입니다. 13행은 11행과 12행의 열을 합한 것입니다. KSH와 솔라리스 5.10을 사용하고 있는데, 입력파일의 값이 연속되지 않을 수도 있고, 3자리 정수를 넘지 않을 수도 있습니다. 내 입력 파일에는 10줄만 있습니다. 이 목표를 달성하는 방법은 무엇입니까?

답변1

$ awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt 
1       10      11
2       20      22
3       30      32
4       40      42
5       50      52
6       60      62
7       70      72
8       80      82
9       90      92
10      100     110
25      250     259
30      300     318
55      550     577

위의 내용은 GNU awk 및 Linux에서 테스트되었습니다.

어떻게 작동하나요?

  • -v OFS='\t'

    선택 사항: 출력이 탭으로 구분되도록 설정합니다.

  • {for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;}; $1=$1; print}

    이는 각 열을 반복하여 해당 값을 배열에 추가합니다 s. 각 열에 대해 i짝수 행이 추가 s[2,i]되고 홀수 행이 추가됩니다 s[1,i]. 모든 행의 열이 i에 추가됩니다 s[3,i].

    그런 다음 라인을 인쇄하십시오.

  • END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}

    파일의 끝에 도달하면 결과가 인쇄됩니다. 먼저 홀수 줄을 인쇄하고( n=1) 짝수 줄을 인쇄한 다음( n=2) 마지막으로 합계를 인쇄합니다( n=3).

썬/솔라리스

Sun/Solaris의 기본 awk에 문제가 있다는 보고를 여러 번 받았습니다. 시도해 보십시오:

nawk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt 

또는:

/usr/xpg4/bin/awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt 

또는:

/usr/xpg6/bin/awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt 

답변2

awk대신에 이것을 사용하고 싶을 것입니다 sed. 다음은 awk이를 수행하는 스크립트입니다.

awk '
    (NR%2) == 1 {
        odd_col_1 += $1;
        odd_col_2 += $2;
        odd_col_3 += $3;
        print $0;
    }
    (NR%2) == 0 {
        even_col_1 += $1;
        even_col_2 += $2;
        even_col_3 += $3;
        print $0;
    }
    END {
        print odd_col_1, odd_col_2, odd_col_3;
        print even_col_1, even_col_2, even_col_3;
        print odd_col_1+even_col_1, odd_col_2+even_col_2, odd_col_3 + even_col_3;
    }
' foo.txt

이는 "NR" 레코드 번호 내장 변수, awk텍스트 파일이 필드로 구분되는 방식 및 "END" 구조를 활용합니다.

답변3

글쎄요, 저는 이 문제에 대한 아주 기본적인 해결책을 스스로 찾았습니다. 그러나 누군가가 더 나은 답변을 갖기를 바랍니다.

#remove even lines
sed -i '0~2d' foo.txt > oddlines

#oddlines sum
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' oddlines > oddlines_sum

#remove even lines
sed -i '1~2d' foo.txt > evenlines

#evenlines sum
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' evenlines > evenlines_sum

#combine 
cat evenlines_sum >> oddlines_sum

#for total sum of foo.txt
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' foo.txt > foo_sum

#final output
cat oddlines_sum >> foo.txt
cat foo_sum >> foo.txt`

나는 내 솔루션이 매우 기본적이라는 것을 알고 있습니다. 하지만 나는 최선을 다했습니다.

답변4

sed '   1x;1s/^/654321/;1x;N;y/ /\n/;G;:t
        s/\([0-9]*\)\n*\n\(.*\)\(.\)/l\3\1+s\3 \2/;tt
        p;$!d;g;s/./l&/g;s/$/fcl3l6+l2l5+l1l4+f/' file |
dc 2>/dev/null |sed '11,$N;/\n/N;s/[^0-9] */\t/g' file -

이것은 당신에게 도움이 될 것입니다. 내부 스트림을 사용하여 dc계산기/컴파일러에 대한 일부 매크로 전처리를 처리하여 작동합니다.sed

기본적으로 sed말해dc ( bc컴파일러 - Solaris 시스템에 있어야 함)6개의 값을 추적하고, 입력 행 하나 걸러 모두 로드하고, 각 열에 대해 값을 증가시킨 후 결과를 다시 저장합니다. 마지막 입력 줄에 다시 호출하라고 sed지시 하고 6개 값을 모두 stdout에 출력합니다. dc13행의 합계를 얻으려면 저장된 합계를 다시 호출하여 더하기만 하면 됩니다.

l3l6+...f

첫 번째 줄에서 어떤 배열에서 값을 로드 하려고 하면 배열이 비어 있고 경고가 발생하기 때문에 dcstderr를 덤프합니다 . 나머지 시간에는 비어 있지 않고 필요할 때 저장/복원하므로 이는 의미가 없습니다./dev/nulll[123456]

마지막으로, 또 다른 하나는 sed모든 것을 하나로 묶습니다. dc출력을 꼬리 부분에 추가합니다.file모든 공백을 한 줄에 하나의 탭으로 바꿉니다.( \t여기서는 이스케이프 문자를 사용하고 있지만 실제 스크립트에서는 리터럴 <tab> 문자여야 합니다).

산출

1       10      11
2       20      22
3       30      32
4       40      42
5       50      52
6       60      62
7       70      72
8       80      82
9       90      92
10      100     110
25      250     259
30      300     318
55      550     577

관련 정보