- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: cut, head, echo
키워드: CSV, 레코드, 컬럼
사용처: CSV 파일에서 인수로 지정한 ID에 대응하는 특정 컬럼을 표시하고 싶을 때
실행예제
$ cat data.csv
0001,Kim,45
0002,Lee,312
0003,Park,102
0004,Kang,3
0005,Seo,92
$ ./csv-select.sh 0004 <----- CSV 파일에서 지정한 ID 컬럼 표시
Kang
스크립트
#!/bin/sh
# CSV 파일 지정
csvfile="data.csv"
# ID가 지정되지 않으면 종료
if [ -z "$1" ]; then #--------------------------------- 1(if문)
echo "ID를 지정하세요" >&2
exit 1
fi
# CSV 파일이 존재하지 않으면 종료
if [ ! -f $csvfile ]; then #--------------------------- 2(if문)
echo "CSV 파일이 존재하지 않습니다: $csvfile" >&2
exit 1
fi
while read line #-------------------------------------- 3
do
# cut 으로 컬럼 추출
id=$(echo $line | cut -f 1 -d ',') #--------------- 4
name=$(echo $line | cut -f 2 -d ',') #------------- 4
score=$(echo $line | cut -f 3 -d ',') #------------ 4
# ID 컬럼이 인수로 지정한 ID와 일치하면 표시
if [ "$1" = "$id" ]; then
echo "$name" #--------------------------------- 6
fi
done < $csvfile #-------------------------------------- 5
해설
이 스크립트는 CSV 파일에서 지정한 ID에 대응하는 필드를 추출해서 표시합니다. 대상 CSV 파일은 “ID번호, 이름, 점수” 형식입니다.
- 예저에서 사용하는 CSV 파일
0001,Kim,45 0002,Lee,312 0003,Park,102 0004,Kang,3 0005,Seo,92
CSV 파일은 엑셀 등에서 자주 사용하는 파일인데 간편한 자료구조라서 유닉스에서도 간단한 리포트 처리 등에서 사용합니다. 셀 스크립트로 CSV 파일을 다룰라면 awk 명령어를 사용하거나 IFS에 ,(쉼표)를 설정하는 등 몇 가지 방법이 있지만 여기에서는 cut 명령어를 사용해 각 항목을 추출합니다.
우선 1
에서 명령행 인수를 확인합니다. 예제에서는 검색할 ID를 인수로 지정하므로 test 명령어 -z 연산자를 써서 인수를 확인하고 없으면 ID를 지정해달라는 에러를 표시하고 종료합니다.
2
에서 CSV 파일 존재를 확인합니다. -f는 대상 파일이 일반 파일인지 확인하는 연산자입니다. 여기에 부정연산자 !를 써서 대상이 디렉터리거나 파일이 존재하지 않으면 에러를 표시하고 종료합니다.
3
에서는 셸 변수 line에 read 명령어를 사용해서 CSV 파일을 읽습니다. 여기서 5
처럼 while문에 입력 리다이렉트를 작성합니다. 이로써 read 명령어로 CSV 파일에서 셸 변수 line에 한 줄씩 순서대로 읽을 수 있습니다.
4
에서는 CSV 파일 줄마다 각 항목을 추출합니다. cut 명령어는 텍스트를 추출할 수 있는 명령어로 -f 명령어로 추출할 필드 번호를 지정하고 -d로 구분자를 지정합니다. 즉 cut -f 1 -d ‘,’는 쉼표 구분자로 첫 번째 필드 추출을 의미합니다.
예제에서 CSV 파일은 “ID번호, 이름, 점수”라는 값이 들어 있다고 가정하므로 4
에서 각각의 항목마다 셸 변수 id, name, score에 명령어 치환 $()를 사용해서 대입합니다.
이렇게 CSV 파일 각 항목이 추출하면 6
에서 셸 스크립트 실행 시 지정한 ID와 현재 읽은 CSV 파일 ID가 일치하는 if문으로 판단합니다. 만약 일치하면 해당하는 ID 줄이므로 앞서 대입한 셸 변수 name값을 echo 명령어로 표시합니다. while문으로 반복해서 전체를 학인하면 CSV 파일에서 해당하는 ID의 이름을 추출할 수 있습니다.
주의사항
-
이 스크립트는 일치한 줄을 그대로 표시하므로 같은 ID를 가진 레코드가 여러 개 있으면 그대로 여러 번 표시합니다.
-
값 자체에 ,(쉼표)가 있는 CSV 파일은 이 스크립트에서 사용할 수 없습니다.
-
data.csv 값에 여러 번 스페이스가 들어 있으면 하나로 합쳐서 표시합니다(“
Kim"은 " Kim"이 됩니다). 이런 동작이 곤란하다면 셸 구분자 IFS에서 스페이스를 제거하고 줄바꿈만 지정합니다. - 예제처럼 이름 컬럼만 표시하는게 아니라 단순히 ID와 일치하는 줄 전체를 표시하고 싶을 때 awk 명령어를 사용한다면 다음과 같습니다.
awk -F, -v id="$1" '$1 == id {print}' data.csv
- -F 옵션에 쉼표를 설정해서 구분자를 지정하고, awk 변수를 지정하는 -v 옵션으로 명령행 인수 $1을 그대로 awk 변수 id로 다룹니다. 그리고 $1(첫 번째 컬럼값)이 id와 일치하면 print문으로 표시합니다.