2012-08-17 74 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

相关问题