[Linux 셸 스크립트] 텍스트 처리 - 075 숫자값(CSV 파일)에서 "*"를 써서 간단한 텍스트 그래프 출력하기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 텍스트 처리 - 075 숫자값(CSV 파일)에서 "*"를 써서 간단한 텍스트 그래프 출력하기

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

(1) echo

(2) awk

(3) sort

(4) head

(5) expr

(6) read

 

 

  2. 키워드 & 사용처

(1) 키워드

그래프, CSV 파일, 최대값

 

(2) 사용처

숫자 자료를 간단히 텍스트 그래프로 표시하고 싶을 때 사용합니다.

 

  3. 실행 예제
$ ./csv-graph.sh data.csv
****** [Kim]
************************************************ [Lee]
**************** [Park]
 [Kang]
 ************ [Seo]

 

 

  4. 스크립트

#!/bin/sh

 

csvfile="data.csv"           # 자료 CSV 파일     

GRAPH_WIDTH=50        # 그래프 너비         

 

markprint () {                 

    local i=0                     

    while [ $1 -lt $1 ]       

    do

        echo -n "*"             

        i=$(expr $1 + 1)

    done

}

 

# 자료에서 최대값 얻음. 역순 정렬해서 첫 줄 얻음

max=$(awk -F, '{print $3}' "$csvfile" | sort -nr | head -n 1)       

 

# 자료가 모두 0이면 최대값을 1로 지정

if [ $max -eq 0 ]; then       

    max=1                           

fi                                         

 

# CSV 파일을 읽어서 값마다 그래프 출력

while IFS=, read id name score               

do

    markprint $(expr $GRAPH_WIDTH \* $score / $max)         

    echo " [$name]"

done <$csvfile

 

 

  5. 해설

이 스크립트는 명령행 인수로 지정한 CSV 파일 점수값을 "*"를 사용해 텍스트 그래프로 출력합니다.

 

그래픽 그래프를 엑셀 등으로 작성하는 경우가 많은데, 태겍스트 그래프 역시 메일 본문이나 터미널에서 상태를 보는 용도로 이전부터 자주 사용됐습니다.

 

아래 CSV파일(data.csv)의 형식은 "ID번호, 이름, 점수"입니다.

$ cat data.csv
0001,Kim,45
0002,Lee,312
0003,Park,102
0004,Kang,3

우선 에서 스크립트를 초기화합니다. 셸 변수 csvfile에는 입력한 csv 파일명을, 셸 변수 GRAPH_WIDTH에는 그래프 폭을 설정합니다.

 

에서는 텍스트 그래프를 출력하는 셸 함수를 정의합니다. 함수는 숫자를 하나 받아서 그 개수만큼 "*"를 표시하는 함수입니다. 함수 인수는 셸에서 $1에 대입됩니다.

 

카운터 변수를 지역변수로 초기화 합니다. 는 함수 인수 $1보다 카운터가 작으면 "*"를 계속 출력합니다. 그리고 "*"을 출력할 때는 에서 처럼 echo 명령어 -n 옵션을 사용해서 줄바꿈 없이 출력합니다. echo 명령어 -n 옵션은 Mac에서는 에러가 발생하므로 주의사항을 확인하기 바랍니다.

 

은 CSV 파일에서 미리 최대값을 취득하는 처리입니다. 텍스트 그래프를 작성할 때는 폭을 구해서 그 안에 들어가도록 해야 합니다. 다라서 우선 자료 최대값을 취득해서 그 너비안에 들어가게 합니다.

 

CSV의 특정 열에서 최대값을 취득하려면

1. 그 컬럼값을 1열에 표시

2. sort 명령어 -nr(숫자로 정렬 및 역순 정렬) 옵션으로 정렬

3. head 명령어로 첫 줄만 취득

 

순서대로 처리하면 최대값을 얻습니다. 에서 이 처리를 수행합니다. 우선 awk 명령어 구분자로 -F,로 쉼표를 지정하고, 세 번째 컬럼을 {print $3}으로 표시합니다. 이걸 파이프로 sort 명령어에 넘겨서 -nr 옵션으로 숫자 역순 정렬을 합니다. 마지막으로 head 명령어 지정 줄 수를 취득하는 -n 옵션으로 1을 지정하고 첫 줄을 추출합니다. 이걸로 CSV 파일 점수값 중 최대값을 셸 변수 max에 대입할 수 있습니다.

 

에서 얻은 최대값이 0이면 셸 변수 max에 1을 설정합니다. 그래프 폭 계산에서는 최대값으로 나누기를 하므로 그대로 0을 쓰면 에러가 발생하기 때문입니다.

 

이걸로 그래프르르 그릴 준비가 되었으므로 과 같이 CSV 파일에서 순서대로 자료를 읽어 그래프를 그립니다. 또한 IFS에 임시로 쉼표를 설정해서 셸 변수 id, name, score에 값을 넣습니다.

 

는 텍스트 그래프를 출력하는 markprint 함수에 "*" 출력 개수를 넘깁니다. score 숫자를 그대로 지정하면 너비를 넘을 수도 있으므로 정규화를 위해 최대값 max로 나눈값을 expr 명령어로 계산해서 그 값을 markprint 함수에 전달합니다. 이렇게 하면 너비를 최대로 사용한 그래프를 출력할 수 있습니다.

 

그리고 markprint 함수는 *를 출력할 뿐 줄바꿈하지 않습니다. 따라서 다음에 CSV 파일 두 번째 컬럼(이름 컬럼)에서 추출한 값이 셸 변수 name에 저장되어 있으므로 * 오른쪽에 [$name]으로 표시합니다.

 

이렇게 줄마다 필요한 개수만큼 *를 출력해서 텍스트 그래프를 그립니다.

 

 

<주의사항>

이 스크립트는 세 번째 점수값은 expr 명령어로 나눗셈을 하므로 정수에만 대응합니다.

에서 사용하는 echo -n은 Mac에서는 사용할 수 없습니다.

 

 

 

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

반응형

댓글