[Linux 셸 스크립트] 텍스트 처리 - 074 숫자로 된 CSV 파일에서 평균값 계산하기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 텍스트 처리 - 074 숫자로 된 CSV 파일에서 평균값 계산하기

by 찬찬이 아빠 2021. 4. 9.
반응형
  1. 사용 명령어

(1) awk

 

  2. 키워드 & 사용처

(1) 키워드

평균값, CSV 파일

 

(2) 사용처

CSV 파일에서 특정 컬럼값의 평균값을 계산해서 파일로 출력하고 싶을 때 사용합니다.

 

 

  3. 실행 예제
$ cat data.csv         <- 자료 파일 확인
0001,Kim,45
0002,Lee,312
0003,Park,102
0004,Kang,3

$ ./csv-avg.sh data.csv
$ cat data.avg          <- 평균값이 기록된 [파일명.avg]이 생성됨
115.5

 

 

  4. 스크립트

#!/bin/sh

 

# CSV 파일이 존재하지 않으면 종료

if [ ! -f "$1" ]; then                   

    echo "대상 CSV 파일이 존재하지 않습니다 : $1" >&2       

    exit 1             

fi

 

# 확장자를 제외한 파일명 취득

filename=${1%.*}           

 

awk -F, '{sum += $3} END{print sum / NR}' "$1" > ${filename}.avg     

 

 

  5. 해설

이 스크립트는 명령행 인수를 지정한 CSV 파일의 세 번째 컬럼에서 값의 평균값을 계산해서 출력합니다. 평균값은 우너본 파일명에 확장자 .avg를 붙인 파일에 출력합니다. 여러 CSV 파일마다 평균값을 출력하고 싶을 때 사용하면 됩니다.

 

여기에서 사용하는 CSV 파일은 "ID번호, 이름, 점수" 형식이라고 가정합니다.

 

셸 스크립트에서 수치 계산은 expr 명령어를 자주 사용합니다. 하지만 expr은 정수 계산만 가능하므로 소수가 포함된 계산에서는 사용할 수 없습니다. 셸 스크립트에서 소수를 포함한 계산을 할 때는 bc 명령어를 사용하기도 하는데 여기에서는 간단히 awk 명령어르르 사용해봅니다.

 

에서 대상 CSV 파일 존재를 확인합니다. -f 옵션은 대상이 일반 파일인지 확인하는데 부정 연산자 !를 함께 서서 대상이 일반 파일이 아니면 에러를 표시하고 종료합니다.

 

에서 파일 확장자를 제외한 파일명을 취득합니다. 여기서 셸 파라미터 확장을 사용한 문장열 치환으로 셸 변수 $1에서 '.(점)과 그 이후에 이어진 임의 문자열'을 제거합니다. $1에는 명령행 인수로  CSV 파일이 넘어오므로 확장자 .csv를 제거할 수 있게 됩니다.

 

③은 평균값을 계산하는 awk 명령어입니다. 우선 awk 명령어에서 구분자로 ,(쉼표)를 지정하기 위해 -F 구분자 지정 옵션에 ,를 설정합니다. awk 명령어 표현은 {}는 각 줄마다 실행하고 END {}는 마지막 줄을 읽은 다음 실행하게 됩니다. 우선 {sum += $3}으로 각 줄의 $3(세 번째 컬럼인 점수)을 변수 sum과 더합니다.

 

END에서 사용한 NR은 awk 내장 변수로 현재 처리한 줄 번호가 들어 있습니다.END{print sum / NR}이 실행되는 것은 마지막 줄이므로 NR에는 파일 줄 수가 들어갑니다. NR값으로 sum을 나누면 점수 평균값을 구할 수 있습니다.

 

점수 평균값은 앞서 확장자를 제외한 파일명에 확장자 .avg를 붙인 파일에 리다이렉트해서 출력합니다.

 

 

<주의사항>

awk에서 구분자를 쉼표로 설정할 때 -F,가 아니라 -F ',' 라고 지정해도 됩니다. 어느 쪽을 사용해도 괜찮지만 다른 사람의 코드를 읽을 때 구 가지 지정 방법이 있다는걸 기억하기 바랍니다.

이 스크립트는 값 자체에 쉼표가 포함된 CSV 파일에 대응하지 않습니다.

예제에서는 CSV 파일 내용을 확인하지 않으므로 만약 빈 파일은 0으로 나누게 되어서 에러가 발생합니다.

 

 

 

참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전

반응형

댓글