2012-08-17 75 views
2

我很難將大的(50GB)csv文件分解爲更小的部分。每行有幾千個字段。一些字段是用雙引號括起來的字符串,其他字段是整數,小數和布爾值。使用字段數量將文件拆分爲更小的文件

我想逐行解析文件並按每行中的字段數拆分。這些字符串可能包含幾個逗號(如),以及一些空字段。

,, 1,30,50 「由父親,兒子和$ 4,000女兒賣」,,,,, 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

那麼,是一列意思是一個文件? – 2012-08-17 00:36:19

+0

這是一行的一部分。有幾百萬行。 – Yoda 2012-08-17 00:40:38

+0

更好地重新導出您的文件與字段分隔符不包含在您的數據。 '|'字符通常是安全的,並且可見,不像其他最喜歡的選項卡字符。祝你好運。 – shellter 2012-08-17 00:41:44

回答

3

使用Python - 如果你只是想分析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'模式,否則多行字段可能無法在python 2.x上工作 – jfs 2012-08-17 00:59:09

+0

第二個示例在第一個示例中不起作用 – jfs 2012-08-17 01:15:44

+0

'csvout.writerows(csv.reader(fin))' – jfs 2012-08-17 01:21:56

2

下面是一個awk替代。

假設引用的字符串很好的格式,即總有開始和結束的報價,和其他引號中沒有報價,你可以做你通過每隔場|更換,gsub建議更換。

隨着管

下面是如何通過6,第11和14-15與抓列3時,這可能提供了一個範例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 2012-08-18 01:23:31

相關問題