제어 구문 예제_04 ID 컬럼을 "00001" 처럼 0으로 채운 CSV 파일에서 번호를 지정해서 값을 추출하기

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

명령어: read, cut, test
키워드: 숫자값, 문자열, 0 채우기
사용처: “00001” 처럼 0으로 채운 문자열을 그대로 숫자로 다루고 싶을 때


실행예제

$ cat data.csv
00001,Busan
2,Kim
3,Park
00004,Seo

$ ./zero-string.sh
Busan  <------------------ ID 번호가 1인 값을 출력

스크립트

#!/bin/sh

# 추출 조건 등 정의
match_id=1          # 추출할 ID  -------------------- 1
csvfile="data.csv"  # CSV 파일 지정  ---------------- 1

# 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

  # ID 컬럼이 셸 변수 match_id로 지정한 ID와 일치하면
  # 이름 필드 표시
  if [ "$id" -eq "$$match_id" ]; then  #------------ 5(if문)
    echo "$name"
  fi
done < "$csvfile"

   

해설

이 스크립트는 CSV 파일에서 ID 번호가 1인 컬럼을 추출합니다. 이때 ‘숫자가 1’이라는 표현에는 1 외에도 00001과 같이 앞부분에 0이 있는 형식도 포함합니다.

예제에서는 다음과 같은 CSV 파일을 다룹니다.

  • 파일1 사용할 CSV 파일(data.csv)

    00001,Busan
    2,Kim
    3,Park
    00004,Seo
    

첫 번째 컬럼에 ID 번호, 두 번째 이름이 있습니다. CSV 파일에 0으로 시작하는 값과 그렇지 않은 값이 섞여 있습니다. 이렇듯 숫자값 앞부분에 0이 있는 숫자 문자열을 보통 숫자값으로 다루는 일이 종종 발생합니다.

예를 들어 sed 명령어 등으로 앞부분 0을 제거하는 방법이 있습니다.

str="00001"

str=$(echo "$str" | sed "s/^0*//"

하지만 셸 스크립트라면 이런 처리가 필요 없습니다. test 명령에서는 같은 값인지 판정하는 -eq 연산자나 expr 명령어 등 숫자값을 다루는 명령어는 0으로 채운 숫자 문자열을 그대로 순수한 숫자값으로 다룰 수 있기 때문입니다.

  • expr 명령어는 0으로 채워도 문제없이 동작

    $ expr "00001" + 1
    2
    

그럼 예제를 살펴봅시다. 1에서 추출할 ID 번호와 대상 CSV 파일을 정의합니다. 2에서는 대상 CSV 파일 존재를 확인합니다. -f는 대상이 일반 파일인지 확인하는 연사자입니다. 파일이 존재하지 않거나 디렉터리이거나 하면 에러를 표시하고 종료합니다.

3에서는 while문의 입력 리다이렉트로 CSV 파일을 한 줄씩 셸 변수 line에 읽어들입니다. 4는 cut 명령어로 추출한 컬럼값을 셸 변수 id와 name에 각각 대입합니다. 이런 csv 파일에서 cut 명령어로 특정 컬럼을 추출하는 방법은 CSV 파일에서 지정한 특정 레코드의 컬럼값 얻기에서 설명했으므로 참조하기 바랍니다.

5에서 ID 번호 컬럼값이 셸 변수 match_id로 정의한 추출해야 할 ID 번호와 일치하는지 판별합니다. 여기서 단순히 추출할 첫 번째 컬럼(셸 변수 id)을 test 명령어 -eq 연산자로 확인합니다. test 명령어 -eq 연산자는 다음처럼 앞부분 0은 신경 쓰지 않아도 됩니다.

# 숫자와 비교하면 앞부분 0은 신경 쓰지 않아도 됨
[ "00001" -eq 1 ]	          -> true
[ "1" -eq 1 ]	              -> true

# 문자열로 비교하면 거짓이 됨
[ "00001" = "1" ]	          -> false

하지만 test 명령어를 =로 비교하면 문자열로 비교하게 되므로 00001과 1은 서로 다른 값이 됩니다. 숫자로 비교하려면 -eq 연산자를 사용해야 합니다.

5는 이렇게 비교해서 참이면 추출해야 할 ID 번호의 name 값을 echo 명령어로 출력합니다. 셸 스크립트에서 숫자 문자열을 간단히 다룰 수 있으므로 CSV 파일을 사용할 때 알아두면 편리합니다.

   

주의사항

  • 이 스크립트는 값에 ,(쉼표)가 있는 CSV 파일에 대응하지 않습니다.