실제 CSV 파일을 정확하게 구문 분석하는 방법이 있습니까? [복사]

실제 CSV 파일을 정확하게 구문 분석하는 방법이 있습니까? [복사]

나는 bash 쉘을 사용하고 있습니다. CSV 파일이 실제 CSV 형식으로 관찰되는 CSV 파일을 구문 분석하고 싶습니다. 이 스레드에서 -https://stackoverflow.com/questions/4286469/how-to-parse-a-csv-file-in-bash, 이해합니다

#!/bin/bash

file_path=$1
echo $1

while IFS=, read -r ID name address zipcode
do
    echo "I got:$ID|$name|$address|$zipcode"
done < $file_path

그러나 CSV 파일에서는 일부 셀 자체에 쉼표가 포함될 수 있으므로 이러한 항목 주위에 따옴표가 있습니다. 따라서 다음 파일을 올바르게 구문 분석할 수 없습니다.

1,1871,"222 W. Merchandise Mart Plaza, Suite 1212",60605

CSV 파일을 정확하게 구문 분석할 수 있도록 위 스크립트를 수정하거나 새 스크립트를 생성하는 방법이 있습니까?

답변1

cvskit필요한 것: CSV 파일을 위한 강력한 grep, 잘라내기, 조인 등. 만 사용하겠습니다 csvformat.

이 경우 나는 다음을 좋아합니다.

(1) 입력 데이터를 "좋은" 구분 기호(예: ","에서 "§"로)로 변환하고 불필요한 따옴표를 제거합니다.

csvformat -d § input | ...

(2) "양호한" 구분 기호를 사용하여 데이터 처리

... | awk 'BEGIN{FS=OFS="§"} ...' | ...

(3) 다시 CSV로 변환("§"에서 ","로) 필요한 경우 따옴표를 추가합니다.

csvformat -D § > final

답변2

입력 파일 a.csv:

1,1111,"111 W. Merchandise Mart's Plaza, Suite 1111",10101
2,2222,"222 Ben's St, Suite 222",20202

Python 3을 사용하여 입력 파일을 구문 분석하기 위한 한 가지 라이너:

$ cat a.csv|python -c $'import csv,sys;reader=csv.reader(sys.stdin);\nfor row in reader: print row'

산출:

['1', '1111', "111 W. Merchandise Mart's Plaza, Suite 1111", '10101']
['2', '2222', "222 Ben's St, Suite 222", '20202']

더 복잡한 한 줄 출력:

$ cat a.csv |python -c $'import csv,sys;reader=csv.reader(sys.stdin);\na=0\nb=0\nfor row in reader:\n\ta+=1\n\tprint "Column",a\n\tfor col in row:\n\t\tb+=1\n\t\tprint "\tColumn",b,":",col'
Column 1
        Column 1 : 1
        Column 2 : 1111
        Column 3 : 111 W. Merchandise Mart's Plaza, Suite 1111
        Column 4 : 10101
Column 2
        Column 5 : 2
        Column 6 : 2222
        Column 7 : 222 Ben's St, Suite 222
        Column 8 : 20202

두 번째 코드 줄의 읽을 수 있는 버전:

import csv,sys;
reader=csv.reader(sys.stdin);
a=0
b=0
for row in reader:
    a+=1
    print "Column",a
    for col in row:
        b+=1
        print "    Column",b,":",col

Gnu awk(멍하니):

$ cat a.csv| awk -vFPAT='[^,]*|"[^"]*"' '{for (i=1; i<=NF; i++) {print ">"$i"<"}; print ""}'
>1<
>1111<
>"111 W. Merchandise Mart's Plaza, Suite 1111"<
>10101<

>2<
>2222<
>"222 Ben's St, Suite 222"<
>20202<

답변3

Excel 출력에서 ​​본 모든 항목을 처리하는 awk 스크립트가 있습니다. 필드의 가변 수, 필요하지 않은 경우에도 필드를 인용합니다. 캐리지 리턴 및 줄 바꿈 변환. 그것을 찾아야 합니다. 여러 형식 간에 변환이 가능하고 약 300줄(자체 매뉴얼 페이지 포함)이 필요한 것 같습니다. 또한 DDL을 지정하는 데 도움이 되는 열에 대한 일부 통계도 수행합니다.

주요 문제는 출력 형식을 결정하는 것입니다. 동일한 문제가 출력에 전파되는 것을 피하기 위해 막대로 구분된 "|" 필드와 $로 구분된 줄 바꿈을 선택했습니다. 예를 들어 열에는 ASCII 0x1f(단위 구분 기호)를 사용하고 필드 내 줄 바꿈에는 0x1D(그룹 구분 기호)를 사용하는 것이 쉽습니다.

다양한 도구와 라이브러리가 언급된 이전 스레드에 대한 참조를 볼 수 있습니다. 나는 중요한 시스템이 잠겨서 다운로드할 수 없게 되었을 때 이 글을 썼습니다. 공급업체의 제품을 망가뜨릴 경우를 대비해 C를 사용하는 것도 허용되지 않았지만 그들은 "나는 스크립트를 작성할 수 있습니다. 스크립트로 어떤 피해도 입힐 수 없습니다."라고 인정했습니다.

관련 정보