Bash에서 CSV 파일을 구문 분석하는 방법은 무엇입니까?


112

긴 Bash 스크립트를 작성 중입니다. CSV 파일의 셀을 Bash 변수로 읽고 싶습니다. 줄과 첫 번째 열을 구문 분석 할 수 있지만 다른 열은 구문 분석 할 수 없습니다. 지금까지 내 코드는 다음과 같습니다.


  cat myfile.csv|while read line
  do
    read -d, col1 col2 < <(echo $line)
    echo "I got:$col1|$col2"
  done

첫 번째 열만 인쇄합니다. 추가 테스트로 다음을 시도했습니다.

read -d, x y < <(echo a,b,)

그리고 $ y는 비어 있습니다. 그래서 나는 시도했다.

read x y < <(echo a b)

그리고 $ y는 b입니다. 왜?


7
당신은 고려 한 awk사용 $1, $2등?
BeemerGuy 2010

4
참고로 : command <<(echo "string") ---> command <<< "string"
tokland

1
'cut'명령 줄 프로그램은이를 위해 설계되었습니다. ss64.com/bash/cut.html
Jay

답변:


215

IFS대신 -d다음 을 사용해야 합니다 .

while IFS=, read -r col1 col2
do
    echo "I got:$col1|$col2"
done < myfile.csv

범용 CSV 구문 분석의 경우 Bash가 자체적으로 처리 할 수없는 다른 문제 중에서도 내부 쉼표로 인용 된 필드를 처리 할 수있는 특수 도구를 사용해야합니다. 이러한 도구의 예는 cvstoolcsvkit입니다.


7
제안 된 솔루션은 매우 간단한 CSV 파일, 즉 헤더와 값에 쉼표와 포함 된 따옴표가없는 경우에 적합합니다. 실제로 일반 CSV 파서를 작성하는 것은 매우 까다 롭습니다 (특히 여러 CSV "표준"이 있기 때문에). CSV 파일을 * nix 도구에 더 적합하게 만드는 한 가지 접근 방식은 Excel을 사용하여 파일을 TSV (탭으로 구분 된 값)로 변환하는 것입니다.
피크

몸에서 mkdir을 할 수 없다는 것이 흥미 롭습니다. 나는 command not found. echo작품 만 .
Zsolt

1
@Zsolt : 그럴 이유가 없습니다. 오타 또는 인쇄되지 않는 문자가 있어야합니다.
추후 공지가있을 때까지 일시 중지되었습니다.

2
사용하는 경우는 구분자 예를 동봉해야 @DennisWilliamson ;:while IFS=";" read col1 col2; do ...
thomas.mc.work

1
@ thomas.mc.work : 세미콜론과 쉘에 특수한 기타 문자의 경우에 해당됩니다. 쉼표의 경우 필요하지 않으며 불필요한 문자는 생략하는 편을 선호합니다. 예를 들어 항상 중괄호 (예 :)를 사용하여 확장 변수를 지정할 수 ${var}있지만 필요하지 않은 경우 생략합니다. 나에게는 더 깨끗해 보인다.
추후 공지가있을 때까지 일시 중지되었습니다.

10

로부터 man페이지 :

-d delim delim의 첫 번째 문자는 줄 바꿈이 아닌 입력 줄을 종료하는 데 사용됩니다.

-d,쉼표에서 입력 줄을 종료하는 사용 중입니다. 나머지 줄은 읽지 않습니다. 이것이 $ y가 비어있는 이유입니다.


3

인용 문자열로 csv 파일을 구문 분석하고 say | 다음 코드로

while read -r line
do
    field1=$(echo $line | awk -F'|' '{printf "%s", $1}' | tr -d '"')
    field2=$(echo $line | awk -F'|' '{printf "%s", $2}' | tr -d '"')

    echo $field1 $field2
done < $csvFile

awk는 문자열 필드를 변수로 구문 분석하고 tr은 따옴표를 제거합니다.

awk가 각 필드에 대해 실행되므로 약간 느립니다.


1
좋습니다. 혼수 상태 (,)를 사용할 수도 있습니다
pkarc

0

일부 줄이있는 CSV 파일을 읽으려면 이것이 해결책입니다.

while IFS=, read -ra line
do 
    test $i -eq 1 && ((i=i+1)) && continue
    for col_val in ${line[@]}
    do
        echo -n "$col_val|"                 
    done
    echo        
done < "$csvFile"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.