【问题标题】:splitting file into smaller files using by number of fields使用按字段数将文件拆分为较小的文件
【发布时间】:2012-08-13 09:35:31
【问题描述】:

我很难将大型 (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,但我可能需要一个实用程序来逐行流式处理文件。

【问题讨论】:

  • 那么,一列是否意味着一个文件?
  • 这是一行的一部分。有几百万行。
  • 最好使用未包含在数据中的字段分隔符重新导出文件。 '|' char 通常是安全且可见的,不像另一个最喜欢的 tab char。祝你好运。

标签: python unix csv sed awk


【解决方案1】:

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

【讨论】:

  • 使用 'rb' 模式,否则多行字段可能无法在 python 2.x 上工作
【解决方案2】:

这是一个awk 替代方案。

假设引用的字符串格式正确,即始终有起始和终止引号,并且在其他引号中没有引号,您可以通过在每个其他字段上使用 gsub, 替换为 @987654324 来完成您建议的替换@。

带管道

下面是使用coreutilscut 抓取第 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])
}

【讨论】:

    猜你喜欢
    • 2013-07-31
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2013-04-23
    • 2012-06-06
    相关资源
    最近更新 更多