- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: echo, awk, sort, head, expr, read
키워드: 그래프, CSV 파일, 최대값
사용처: 숫자 자료를 간단히 텍스트 그래프로 표시하고 싶을 때
실행예제
$ ./csv-graph.sh data.csv
****** [Kim]
************************************************ [Lee]
**************** [Park]
[Kang]
************ [Seo]
스크립트
#!/bin/sh
csvfile="data.csv" # 자료 CSV 파일 ----------------- 1
GRAPH_WIDTH=50 # 그래프 너비 ------------------------1
markprint() { #------------------------------------ 2
local i=0 #-------------------------------------- 3
while [ $i -lt $1 ] #---------------------------- 4
do
echo -n "*" #---------------------------------- 5
i=$(expr $i + 1)
done
}
# 자료에서 최댓값 얻음. 역순 정렬해서 첫 줄 얻음
max=$(awk -F, 'print $3' "$csvfile" | sort -nr | head -n 1) #--- 6
# 자료가 모두 0이면 최댓값을 1로 지정
if [ $max -eq 0 ]; then # ---------------------------------------7(if문)
max=1
fi
# CSV 파일을 읽어서 값마다 그래프 출력 ----------------------------- 8
while IFS=, read id name score
do
markprint $(expr $GRAPH_WIDTH \* $score / $max) #------------- 9
echo " [$name]"
done < $csvfile
해설
이 스크립트는 명령행 인수로 지정한 CSV 파일 점수값을 “*“를 사용해 텍스트 그래프로 출력합니다.
그래픽 그래프를 엑셀 등으로 작성하는 경우가 많은데, 태겍스트 그래프 역시 메일 본문이나 터미널에서 상태를 보는 용도로 이전부터 자주 사용됐습니다.
아래 CSV파일(data.csv)의 형식은 “ID번호, 이름, 점수”입니다.
파일1
CSV파일(data.csv)0001,Kim,45 0002,Lee,312 0003,Park,102 0004,Kang,3 0005,Seo,92
우선 1
에서 스크립트를 초기화합니다. 셸 변수 csvfile에는 입력한 csv 파일명을, 셸 변수 GRAPH_WIDTH에는 그래프 폭을 설정합니다.
2
에서는 텍스트 그래프를 출력하는 셸 함수를 정의합니다. 함수는 숫자를 하나 받아서 그 개수만큼 “*“를 표시하는 함수입니다. 함수 인수는 셸에서 $1에 대입됩니다.
3
은 카운터 변수를 지역변수로 초기화 합니다.
4
는 함수 인수 $1보다 카운터가 작으면 "*"
를 계속 출력합니다. 그리고 "*"
을 출력할 때는 echo 명령어 -n 옵션을 사용해서 줄바꿈 없이 출력합니다
5
.
**echo 명령어 -n 옵션은 Mac에서는 에러가 발생하므로 주의사항을 확인하기 바랍니다.
6
은 CSV 파일에서 미리 최대값을 취득하는 처리입니다. 텍스트 그래프를 작성할 때는 폭을 구해서 그 안에 들어가도록 해야 합니다. 따라서 우선 자료 최대값을 취득해서 그 너비안에 들어가게 합니다.
CSV의 특정 열에서 최대값을 취득하려면
- 그 컬럼값을 1열에 표시
- sort 명령어 -nr(숫자로 정렬 및 역순 정렬) 옵션으로 정렬
- head 명령어로 첫 줄만 취득
순서대로 처리하면 최대값을 얻습니다. 6
에서 이 처리를 수행합니다. 우선 awk 명령어 구분자로 -F,로 쉼표를 지정하고, 세 번째 컬럼을 {print $3}으로 표시합니다. 이걸 파이프로 sort 명령어에 넘겨서 -nr 옵션으로 숫자 역순 정렬합니다. 마지막으로 head 명령어 지정 줄 수를 취득하는 -n 옵션으로 1을 지정하고 첫 줄을 추출합니다. 이걸로 CSV 파일 점수값 중 최대값을 셸 변수 max에 대입할 수 있습니다.
7
은 6
에서 얻은 최대값이 0이면 셸 변수 max에 1을 설정합니다. 그래프 폭 계산에서는 최대값으로 나누기를 하므로 그대로 0을 쓰면 에러가 발생하기 때문입니다.
이걸로 그래프르르 그릴 준비가 되었으므로 8
과 같이 CSV 파일에서 순서대로 자료를 읽어 그래프를 그립니다. 또한 IFS에 임시로 쉼표를 설정해서 셸 변수 id, name, score에 값을 넣습니다.
9
는 텍스트 그래프를 출력하는 markprint 함수에 "*"
출력 개수를 넘깁니다. score 숫자를 그대로 지정하면 너비를 넘을 수도 있으므로 정규화를 위해 최대값 max로 나눈 값을 expr 명령어로 계산해서 그 값을 markprint 함수에 전달합니다. 이렇게 하면 너비를 최대로 사용한 그래프를 출력할 수 있습니다.
그리고 markprint 함수는 *를 출력할 뿐 줄바꿈하지 않습니다. 따라서 9
다음에 CSV 파일 두 번째 컬럼(이름 컬럼)에서 추출한 값이 셸 변수 name에 저장되어 있으므로 * 오른쪽에 [$name]으로 표시합니다.
이렇게 줄마다 필요한 개수만큼 *를 출력해서 텍스트 그래프를 그립니다.
주의사항
-
이 스크립트는 세 번째 점수값은 expr 명령어로 나눗셈을 하므로 정수에만 대응합니다.
-
5
에서 사용하는 echo -n은 Mac에서는 사용할 수 없습니다.