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,但我可能需要一个实用程序来逐行处理文件。

4

2 回答 2

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()
于 2012-08-17T00:50:02.687 回答
2

这是一个awk替代方案。

假设引用的字符串格式正确,即始终具有起始和终止引号,并且在其他引号中没有引号,您可以通过gsub在每个其他字段上替换,|.

带管道

以下是使用 抓取第 3 到 6、11 和 14-15 列时可能发生的情况的示例coreutils cut

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 列:

提取.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])
}
于 2012-08-17T11:55:45.700 回答