2012-08-17 2 views
2

큰 (50GB) CSV 파일을 작은 부분으로 나누는 데 어려움을 겪고 있습니다. 각 라인에는 수천 개의 필드가 있습니다. 필드 중 일부는 큰 따옴표로 묶인 문자열이고, 다른 부분은 정수, 소수 및 부울입니다.필드 수로 파일을 작은 파일로 나누기

줄 단위로 파일을 구문 분석하고 각 행의 필드 수로 나누고 싶습니다. 문자열에는 여러 개의 쉼표 (예 :)와 여러 개의 빈 필드가 포함될 수 있습니다.

내가

를 사용하여 시도 "아버지, 아들과 $ 4,000의 딸에 의해 판매"

,, 1,30,50, ,,,, (12) ,,, 20.9,0,

perl -pe' s{("[^"]+")}{($x=$1)=~tr/,/|/;$x}ge ' file >> file2 

따옴표 안에 쉼표를 변경하려면 | 그러나 그것은 작동하지 않았다. 사용할 계획입니다

awk -F"|" conditional statement appending to new k_fld_files file2 

더 쉬운 방법이 있습니까? 나는 python을보고 있지만 아마도 파일을 한 줄씩 처리하는 유틸리티를 필요로 할 것이다. 파이썬을 사용하여

+0

, 한 열은 하나 개의 파일로 의미? –

+0

그건 한 줄의 일부입니다.몇 백만 줄이 있습니다. – Yoda

+0

데이터에 포함되지 않은 필드 구분 기호로 파일을 다시 내보내는 것이 좋습니다. '|' char는 다른 좋아하는 것과는 달리 일반적으로 안전하고 눈에 보이며 탭 char입니다. 행운을 빕니다. – shellter

답변

3

- 당신은 그냥 내장 구분 기호를 포함하는 CSV를 구문 분석, 새로운 구분와 같은, 무언가 밖으로 스트리밍하려면 : 그렇지 않으면

import csv 
import sys 
with open('filename.csv') as fin: 
    csvout = csv.writer(sys.stdout, delimiter='|') 
    for row in csv.reader(fin): 
     csvout.writerow(row) 

을,이 모든 할 수 있도록 훨씬 더 어렵지 않다 종류의 물건. (안된) 열당 파일 출력

예 :

cols_to_output = {} 
for row in csv.reader(fin): 
    for colno, col in enumerate(row): 
     output_to = cols_to_output.setdefault(colno, open('column_output.{}'.format(colno), 'wb') 
     csv.writer(output_to).writerow(row) 

for fileno in cols_to_output.itervalues(): 
    fileno.close() 
+0

'rb'모드를 사용하면 그렇지 않으면 여러 줄 필드가 파이썬 2.x에서 작동하지 않을 수 있습니다. – jfs

+0

두 번째 예제는 작동하지 않습니다. – jfs

+0

첫 번째 예제에서'csvout.writerows (csv.reader (fin)) ' – jfs

2

은 여기 awk 대안이다. 인용 된 문자열이 아니라 즉 항상 시작하고 따옴표를 종료하고 다른 따옴표 안에 따옴표, 당신은 당신이 |,을 대체하는 다른 모든 필드에 gsub을 수행하여 제안 교체를 할 수 없었다 한 형식이 가정

. 파이프 아래

는 6, 11, 14 ~ 15을 통해 열 셋을 잡는 경우이 갈 수있는 방법의 예입니다 coreutilscut : 추가가 있음을

awk -F'"' -v OFS='' ' 
    NF > 1 { 
    for(i=2; i<=NF; i+=2) { 
     gsub(",", "|", $i); 
     $i = FS $i FS;  # reinsert the quotes 
    } 
    print 
    }'\ 
| cut -d , -f 3-6,11,14-15 \ 
| awk -F'"' -v OFS='' -e ' 
    NF > 1 { 
     for(i=2; i<=NF; i+=2) { 
     gsub("\\|", ",", $i) 
     $i = FS $i FS;  # reinsert the quotes 
     } 
     print 
    }' 

|,으로 되 돌리는 사후 처리 단계.

전적으로

또는 AWK, 당신은 범위 지정에 관해서 일반성의 일부 손실 awk에 모든 일을 할 수 있었다. 여기에서 우리는 열이 3 ~ 6 잡아 :

extract.awk 그래서

BEGIN { 
    OFS = "" 
    start = 3 
    end = 6 
} 
{ 
    for(i=2; i<=NF; i+=2) { 
    gsub(",", "|", $i) 
    $i = FS $i FS 
    } 
    split($0, record, ",") 
    for(i=start; i<=end-1; i++) { 
    gsub("\\|", ",", record[i]) 
    printf("%s,", record[i]) 
    } 
    gsub("\\|", ",", record[end]) 
    printf("%s\n", record[end]) 
} 
+0

이것은 완벽하게 작동했습니다. 고맙습니다. – Yoda

관련 문제