다음 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
s
0으로 초기화할 필요는 없습니다 . 에서는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부터 레코드 수까지 반복하여 올바른 행을 출력하고 백분율을 계산합니다.