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에서는 사용할 수 없습니다.
참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전
'IT 이야기 > Linux 셸 스크립트' 카테고리의 다른 글
[Linux 셸 스크립트] 텍스트 처리 - 077 웹 서버 로그 파일에서 특정 상태값만 취득하기 (0) | 2021.04.12 |
---|---|
[Linux 셸 스크립트] 텍스트 처리 - 076 로그 파일 컬럼 위치를 바꿔서 출력하고 보기 쉽게 바꾸기 (0) | 2021.04.12 |
[Linux 셸 스크립트] 텍스트 처리 - 074 숫자로 된 CSV 파일에서 평균값 계산하기 (0) | 2021.04.09 |
[Linux 셸 스크립트] 텍스트 처리 - 073 CSV 파일에 ID 목록을 입력해서 대응하는 ID 컬럼값 얻기 (0) | 2021.04.08 |
[Linux 셸 스크립트] 텍스트 처리 - 072 CSV 파일에서 지정한 특정 레코드의 컬럼값 얻기 (0) | 2021.04.08 |
댓글