[Linux 셸 스크립트] 텍스트 처리 - 072 CSV 파일에서 지정한 특정 레코드의 컬럼값 얻기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 텍스트 처리 - 072 CSV 파일에서 지정한 특정 레코드의 컬럼값 얻기

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

(1) cut

(2) read

(3) echo

 

  2. 키워드 & 사용처

(1) 키워드

CSV, 레코드, 컬럼

 

(2) 사용처

CSV 파일에서 인수로 지정한 ID에 대응하는 특정 컬럼을 표시하고 싶을 때 사용합니다.

 

  3. 실행 예제
$ 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

 

 

  4. 스크립트

$li#!/bin/sh

 

# CSV 파일 지정

csvfile="data.csv"

 

# ID가 지정되지 않으면 종료

if [ -z "$1" ]; then                               

    echo "ID를 지정하세요." >&2         

    exit 1                                             

fi

 

# CSV 파일이 존재하지 않으면 종료

if [ ! -f "$csvfile ]; then         

    echo "CSV 파일이 존재하지 않습니다: $csvfile" >&2     

    exit 1           

fi

 

while read line             

do

    # cut으로 컬럼 추출

    id=$(echo $line | cut -f 1 -d ',')           

    name=$(echo $line | cut -f 2 -d ',')     

    score=$(echo $line | cut -f 3 -d ',')     

 

    # ID 컬럼이 인수로 지정한 ID와 일치하면 표시

    if [ "$1" = "$id" ]; then

        echo "$name"               

    fi

done < $csvfile                 

 

 

  5. 해설

이 스크립트는 CSV 파일에서 지정한 ID에 대응하는 필드를 추출해서 표시합니다. 대상 CSV 파일은 "ID번호, 이름, 점수" 형식입니다.

0001,Kim,45
0002,Lee,312
0003,Park,102
0004,Kang,3
0005,Seo,92

CSV 파일은 엑셀 등에서 자주 사용하는 파일인데 간편한 자료구조라서 유닉스에서도 간단한 리포트 처리 등에서 사용합니다. 셀 스크립트로 CSV 파일을 다룰라면 awk 명령어를 사용하거나 IFS에 ,(쉼표)를 설정하는 등 몇 가지 방법이 있지만 여기에서는 cut 명령어를 사용해 각 항목을 추출합니다.

 

우선 에서 명령행 인수를 확인합니다. 예제에서는 검색할 ID를 인수로 지정하므로 test 명령어 -z 연산자를 써서 인수를 확인하고 없으면 ID를 지정해달라는 에러를 표시하고 종료합니다.

 

에서 CSV 파일 존재를 확인합니다. -f는 대상 파일이 일반 파일인지 확인하는 연산자입니다. 여기에 부정연산자 !를 써서 대상이 디렉터리거나 파일이 존재하지 않으면 에러를 표시하고 종료합니다.

 

에서는 셸 변수 line에 read 명령어를 사용해서 CSV 파일을 읽습니다. 여기서 처럼 while문에 입력 리다이렉트를 작성합니다. 이로써 read 명령어로 CSV 파일에서 셸 변수 line에 한 줄씩 순서대로 읽을 수 있습니다.

 

에서는 CSV 파일 줄마다 각 항목을 추출합니다. cut 명령어는 텍스트를 추출할 수 있는 명령어로 -f 명령어로 추출할 필드 번호를 지정하고 -d로 구분자를 지정합니다. 즉 cut -f 1 -d ','는 쉼표 구분자로 첫 번째 필드 추출을 의미합니다.

 

예제에서 CSV 파일은 "ID번호, 이름, 점수"라는 값이 들어 있다고 가정했으므로 에서 각각의 항목마다 셸 변수 id, name, score에 명령어 치환 $()을 사용해서 대입합니다.

 

이렇게 CSV 파일 각 항목이 추출하면 에서 셸 스크립트 실행 시 지정한 ID와 현재 읽은 CSV 파일 ID가 일치하는 if문으로 판단합니다. 만약 일치하면 해당하는 ID 줄이므로 앞서 대입한 셸 변수 name값을 echo 명령어로 표시합니다. while문으로 반복해서 전체를 학인하면 CSV 파일에서 해당하는 ID의 이름을 추출할 수 있습니다.

 

 

<주의사항>

이 스크립트는 일치한 줄을 그대로 표시하므로 같은 ID를 가진 레코드가 여러 개 있으면 그대로 여러 번 표시합니다.

 

값 자체에 ,(쉼표)가 있는 CSV 파일은 이 스크립트에서 사용할 수 없습니다.

 

data.csv 값에 여러 번 스페이스가 들어 있으면 하나로 합쳐서 표시합니다("<space><space>Kim"은 "<space>Kim"이 됩니다). 이런 동작이 곤란하다면 셸 구분자 IFS에서 스페이스를 제거하고 줄바꾸만 지정합니다.

 

예제처럼 이름 컬럼만 표시하는게 아니라 단순히 ID와 일치하는 줄 전체를 표시하고 싶을 때 awk 명령어를 사용한다면 다음과 같습니다.

awk -F, -v id="$1" '$1 == id {print}' data.csv

-F 옵션에 쉼표를 설정해서 구분자를 지정하고, awk 변수를 지정하는 -v 옵션으로 명령행 인수 $1을 그대로 awk 변수 id로 다룹니다. 그리고 $1(첫 번째 컬럼값)이 id와 일치하면 print문으로 표시합니다.

 

 

 

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

반응형

댓글