텍스트처리_05 CSV 파일에서 지정한 특정 레코드의 컬럼값 얻기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: 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문으로 표시합니다.