【问题标题】:Split a large flat file by first two characters on each line按每行的前两个字符拆分大型平面文件
【发布时间】:2015-01-07 08:14:01
【问题描述】:

我有一个大约 10 GB 的大文件,用逗号分隔。每行以 2 个字符的代码开头,该代码告诉它是什么类型的行,因为每行是不同类型的事件。目前我将文件读入 R,然后使用正则表达式根据代码将其拆分为不同的部分,然后将生成的对象写入平面文件。

我很好奇在 Python、bash、sed/awk、等等

数据如下所示:

01,tim@bigcompany.com,20140101120000,campaign1
02,201420140101123000,123321,Xjq12090,TX
02,201420140101123000,123321,Xjq12090,AK
...

任何建议将不胜感激。

【问题讨论】:

  • grep "^01" file > 01.txt
  • @mark-setchell :这将读取整个大文件 n 次。在这种特殊情况下,它将读取 70 GB 而不是 10GB!

标签: python regex bash awk sed


【解决方案1】:

使用 awk 你可以做到:

awk -F, '{fn=$1 ".txt"; print > fn}' file

如果你想通过关闭所有文件句柄来保持它的清洁,请使用awk

awk -F, '!($1 in files){files[$1]=$1 ".txt"} {print > files[$1]}
    END {for (f in files) close(files[$f])}' file

【讨论】:

  • 脚本结束时所有文件都已关闭,为什么要在 END 块中关闭它们?做{print > files[$1];close(files[$1])} 不是更干净吗?
  • 好吧,如果 awk 自动关闭所有文件,那么第一个命令也可以。我在某处读到旧的 awk 版本不会自动执行此操作,因此我给出了第二个命令作为替代。此外{print > files[$1];close(files[$1])} 将在每一行之后关闭文件,并且对于 ~10GB 的数据效率不高。
【解决方案2】:

如果您不关心性能,或者信任您的操作系统/文件系统/驱动器的磁盘缓存:

with open('hugedata.txt') as infile:
    for line in infile:
        with open(line[:2] + '.txt', 'a') as outfile:
            outfile.write(line)

但是,不断地重新打开和重新关闭(因此刷新)文件将意味着您永远无法从缓冲中受益,并且磁盘缓存只能做很多事情来弥补这一点,因此,您可能想要考虑预先打开所有文件。由于只有 7 个,这很容易:

files = { format(i, '{:02}'): open(format(i, '{:02}.txt'), 'w') for i in range(1, 8)}
try:
    with open('hugedata.txt') as infile:
        for line in infile:
            files[line[:2]].write(line)
finally:
    for file in files:
        file.close()

或者,更稳健:

files = collections.defaultdict(lambda s: open(s+'.txt', 'w'))
try:
    with open('hugedata.txt') as infile:
        for line in infile:                
            files[line[:2]].write(line)
finally:
    for file in files:
        file.close()

(您可以编写一个自动关闭的with 语句,但在不同的 Python 版本中会有所不同;这有点笨拙,但适用于从 2.4 到 3.5 甚至更高版本的所有内容,并且因为你没有告诉我们你的平台或 Python 版本,它似乎更安全。)

【讨论】:

    【解决方案3】:

    在 Python 中这样的事情怎么样:

    for line in file('hugedata.txt'):
        fh = file(line[:2] + '.txt', 'a')
        fh.write(line)
    

    【讨论】:

    • 我认为您不想打开文件并只是泄漏它们。特别是如果您要在几分之一毫秒后重新打开它们。此外,除非您需要使用 Python 2.2,否则不要使用 file
    【解决方案4】:

    我会这样做:

    grep '^01' your-10gb-file > 01.csv
    

    然后您可以像这样将其包装在 foreach(用于 tcsh)中:

    foreach n ( `seq -f '%02g' 7` )
        grep '^$n' your-10gb-file > $n.csv
    end
    

    【讨论】:

      【解决方案5】:
      from itertools import groupby
      with open("largefile.txt") as f:
          for k,v in groupby(f,lambda x: x[:2]):
              with open("{}.txt".format(k),"w") as f1:
                  f1.writelines(v)
      

      【讨论】:

        猜你喜欢
        • 2014-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-14
        • 1970-01-01
        • 1970-01-01
        • 2020-02-03
        相关资源
        最近更新 更多