按照字段数量将文件分割成更小的文件

我很难将一个大的(50GB)csv文件分解成小部分。 每行有几千个字段。 一些字段是双引号的string,其他的是整数,小数和布尔值。

我想逐行parsing文件,并按每行的字段数分割。 这些string可能包含几个逗号(如),以及一些空字段。

,, 1,30,50,“父子,女儿卖4000元”,,,,, 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,但我可能需要一个实用程序,将stream处理文件,逐行。

使用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() 

这是一个awk选择。

假设引用的字符串格式良好,即始终有起始和终止引号,并且在其他引号内没有引号,则可以通过在每个其他字段上执行gsub来替代您所建议的替换|

用管道

下面是一个例子,说明如何在使用coreutils cut 3列到第6列,第11列和第14-15列的时候这样做:

 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]) }