평균값을 인쇄하는 쉘 프로그램

평균값을 인쇄하는 쉘 프로그램

내가 해야 할 일은 파일에서 데이터가 포함된 행을 읽는 avgs라는 쉘 프로그램을 작성하는 것입니다. 여기서 헤더 행은 데이터의 어느 곳에나 있을 수 있습니다.

마지막 두 열의 합계를 계산하고 계산해야 하며 합계 및 계산에 첫 번째 행의 데이터를 포함하면 안 됩니다.

다음은 데이터가 포함된 파일입니다.

92876035 SMITZ  S 15 26
95908659 CHIANG R 10 29
SID      LNAME  I T1/20 T2/30
92735481 BRUCE. R 16 28
93276645  YU    C 17 27
91234987 MYRTH  R 15 16

쉘 프로그램은 표준 출력에 다음 줄을 기록합니다: "Theaverage is 17 and 24"

이것이 내가 시도한 것이지만 작동하지 않습니다

count_ppl=0
total=0
while read ?? ?!
do
    total=$((sum+b))
    count_ppl=$((count_ppl+1))
done < filename
avg=$(echo "scale=2;$total/$count_ppl" | bc)
echo "The averages are = $avg"

"읽는 동안" 옆에 "??"와 "?!"가 있는 이유는 거기에 무엇을 넣어야 할지 모르기 때문입니다.

이것은 한 열의 하나의 평균을 계산할 수 있을 것 같지만 열에서 데이터를 가져와 두 개의 평균을 계산하려면 어떻게 해야 합니까?

(BTW, 이것은 bash입니다).

답변1

"첫 번째 행의 데이터는 합계 및 개수에 포함되어서는 안 됩니다"라는 말이 무슨 뜻인지 잘 모르겠습니다. "92876035 SMITZ S 15 26" 행을 제외해야 한다는 의미입니까, 아니면 "SID LNAME I T1/20 T2/30"이 "합계"되지 않았다는 의미입니까?

필요한 변수 이름으로 바꿔야 ??합니다 . ?!마지막으로 언급된 변수 이름은 나머지 입력을 보유합니다. 마지막 두 개의 열이 필요하므로 귀하의 경우에는 5개의 열이 있으며 명령문은 다음 while read과 같습니다.

while read col1 col2 col3 col4 col5

다음으로 행이 헤더 행인지 확인해야 합니다. 이 예에서는 첫 번째 열의 SID라는 단어를 테스트하겠습니다.

if [ "$col1" != 'SID' ]

여기에서 계산을 시작할 수 있습니다.

totallines=$((totallines+1))
sumcol4=$((sumcol4+col4))
sumcol5=$((sumcol5+col5))

마지막으로 다음을 사용하여 평균을 계산할 수 있습니다.

avgcol4=$(echo "scale=2; $sumcol4/$totallines"|bc)
avgcol5=$(echo "scale=2; $sumcol5/$totallines"|bc)

종료하려면 다음 스크립트를 사용할 수 있습니다.

#!/bin/bash
while read col1 col2 col3 col4 col5
do
  if [ "$col1" != 'SID' ]
  then
      totallines=$((totallines+1))
      sumcol4=$((sumcol4+col4))
      sumcol5=$((sumcol5+col5))
  fi
done < /path/to/inputfile
avgcol4=$(echo "scale=2; $sumcol4/$totallines"|bc)
avgcol5=$(echo "scale=2; $sumcol5/$totallines"|bc)
printf "The averages are %s and %s" $avgcol4 $avgcol5

또 다른 방법은 다음을 사용하는 것입니다 awk.

awk '{ if ( $1 != "SID" ) { COL4+=$4; COL5+=$5; } } END { LINES=NR-1; printf "The averages are %.2f and %.2f\n", COL4/LINES, COL5/LINES }' < /path/to/inputfile

위 명령은 헤더 행을 필터링하고 그렇지 않으면 열 4와 5를 합산합니다. 입력 파일을 처리한 후 LINES 변수를 레코드 수에서 1(헤더 행)을 뺀 수로 설정하고 출력 라인을 인쇄합니다.

bash버전이 awk출력됩니다.

The averages are 14.60 and 25.20

답변2

#!/usr/bin/awk -f

NR == 1     { next }
/^[^0-9]/   { next }

{
    s1 += $(NF - 1)
    s2 += $NF
    ++n;
}

END {
    printf("The averages are %.2f and %.2f\n", s1/n, s2/n)
}

시험:

$ chmod +x avgs
$ ./avgs file
The averages are 14.50 and 25.00

awk이는 데이터의 첫 번째 줄(질문에서 요청한 대로)과 첫 번째 문자로 숫자가 아닌 값이 포함된 모든 줄을 건너뛰는 데 사용됩니다 .

다른 모든 행의 경우 마지막 두 필드의 숫자를 twe sum에 추가하고 s1counter s2도 증가시킵니다 n.

마지막으로 결과를 소수점 이하 두 자리까지 출력합니다.

쉘의 "라인"으로:

$ awk 'NR==1||/^[^0-9]/{next} {s1+=$(NF-1);s2+=$NF;++n} END {printf("The averages are %.2f and %.2f\n", s1/n, s2/n)}' file
The averages are 14.50 and 25.00

관련된:

관련 정보