AWK를 사용하여 합계 계산 및 나누기

AWK를 사용하여 합계 계산 및 나누기

다음 data서류를 보면...

foo     10
bar     20
oof     50
rab     20

...두 번째 열 전체에 대한 백분율로 두 번째 열을 인쇄하려면 어떻게 해야 하나요? 즉, 내가 원하는 것은...

foo     10    10%
bar     20    20%
oof     50    50%
rab     20    20%

...물론 덜 분명한 숫자도 있습니다. 누계를 쉽게 만들 수 있지만 방법을 모르겠습니다.행을 인쇄하기 전에 합계 계산. 나는 이것을 awk 파일에서하고 있습니다 totals.awk...

#!/usr/bin/awk -f
BEGIN{
        runningtotal=0
}
{
        runningtotal=runningtotal+$2
        print $1 "\t" $2 "\t" runningtotal "\t" $2/runningtotal
}

그래서 달리기는 ./totals.awk data돌아옵니다...

foo     10      10      1
bar     20      30      0.666667
oof     50      80      0.625
rab     20      100     0.2

총계를 계산하기 위해 한 번, 줄을 인쇄하기 위해 한 번, 두 번 반복하는 방법이 있습니까? AWK에서 이것이 가능합니까? 아니면 다른 유틸리티를 사용해야 합니까?

답변1

단일 호출로 테이블을 생성하려면 다음을 수행하십시오 awk.

$ awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' data data
foo     10      10%
bar     20      20%
oof     50      50%
rab     20      20%

어떻게 작동하나요?

파일은 매개변수로 두 번 data제공됩니다 . awk따라서 두 번 읽혀집니다. 첫 번째는 총계(변수에 저장됨)를 가져오고 s두 번째는 출력을 인쇄하는 것입니다. 명령을 더 자세히 확인하세요.

  • FNR==NR{s+=$2;next;}

    NR은 읽은 레코드(행)의 총 개수이고 awk, FNR은 현재 파일에서 지금까지 읽은 레코드의 개수입니다. 따라서 , FNR==NR우리는 첫 번째 파일을 읽고 있습니다. 이런 일이 발생하면 변수는 s두 번째 열의 값만큼 증가됩니다. 그런 다음 나머지 명령을 건너뛰고 다음 레코드부터 시작하라고 next지시합니다 .awk

    s0으로 초기화할 필요는 없습니다 . 에서는 awk기본적으로 모든 숫자 변수가 0으로 초기화됩니다.

  • printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s

    이 명령에 도달하면 두 번째 파일을 처리하는 중입니다. 이는 s이제 열 2의 합계가 저장되었음을 의미합니다. 따라서 열 1, 열 2 및 백분율을 인쇄합니다 100*$2/s.

출력 형식 옵션

을 사용하면 printf출력 형식을 세부적으로 제어할 수 있습니다. 위 명령은 %s문자열, 정수 및 부동 소수점 숫자에 적합한 형식 지정자를 사용합니다. 여기서 유용할 수 있는 다른 세 가지 옵션은 다음과 같습니다.

  • %d숫자의 형식을 정수로 지정합니다. 숫자가 실제로 부동 소수점인 경우 정수로 잘립니다.

  • %f숫자를 부동 소수점 숫자 형식으로 지정합니다. 너비와 소수 자릿수를 지정할 수도 있습니다(예: ) %5.2f.

  • %e지수 표기법을 제공합니다. 이는 일부 숫자가 특히 크거나 작은 경우에 유용합니다.

쉘 함수 만들기

이 명령을 여러 번 사용하려는 경우 긴 명령을 입력하는 것이 불편할 수 있습니다. 대신 명령을 실행하는 함수나 스크립트를 만드세요.

라는 함수를 생성하려면 totals다음 명령을 실행합니다.

$ totals() { awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' "$1" "$1"; }

data이 함수를 정의한 후 다음을 실행하여 호출된 데이터 파일의 비율을 확인할 수 있습니다.

$ totals data

정의를 totals영구적으로 만들려면 파일에 넣으세요 ~/.bashrc.

쉘 스크립트 만들기

스크립트를 선호하는 경우 totals.sh다음 내용이 포함된 파일을 생성하세요.

#!/bin/sh
awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' "$1" "$1"

라는 데이터 파일의 백분율을 얻으려면 다음을 data실행하십시오.

sh totals.sh data

답변2

이를 수행하는 "쉬운" 방법은 awk두 번 호출하는 것입니다. 한 번은 합계를 구하고 다른 한 번은 비율을 계산합니다.

$ total=$(awk 'BEGIN{ total=0 } { total=total+$2 } END{ printf total }' data)
$ awk -v total=$total '{ print $1 "\t" $2 "\t" 100*$2/total "%" }' data

이제 누군가가 어떻게든 재치 있는 말을 해줄 거라고 확신합니다...

답변3

awk로 파일 열기(완전성을 위해)

awk '{a[NR]=$0;x+=(b[NR]=$2)}END{while(++i<=NR)print a[i]"\t"100*b[i]/x"%"}' file

foo     10      10%
bar     20      20%
oof     50      50%
rab     20      20%

이 방법은 다른 방법보다 더 많은 메모리를 사용하지만 더 빠릅니다.

그러면 행을 array 로 읽고 a필드 2를 array 로 읽 습니다 b.
그런 다음 x필드 2의 값만큼 증가합니다.

마지막으로 1부터 레코드 수까지 반복하여 올바른 행을 출력하고 백분율을 계산합니다.

관련 정보