【问题标题】:Split file with 800,000 columns使用 800,000 列拆分文件
【发布时间】:2017-04-21 05:32:09
【问题描述】:

我想将一个包含 800,000 列和 40,000 行的基因组数据文件拆分为一系列文件,每个文件包含 100 列,总大小为 118GB。

我目前正在运行以下 bash 脚本,多线程 15 次:

infile="$1"
start=$2
end=$3
step=$(($4-1))

for((curr=$start, start=$start, end=$end; curr+step <= end; curr+=step+1)); do
  cut -f$curr-$((curr+step)) "$infile" > "${infile}.$curr" -d' '
done

不过,以目前剧本的进度来看,完成拆分需要300天?!

有没有更有效的方法来按列将空格分隔的文件分成更小的块?

【问题讨论】:

  • 您可以尝试在每次循环迭代时在后台多次运行 cut 命令,或者您可以考虑其他一些并行运行的方式。
  • @Aserre:我认为它们不是完全重复的,因为这个要求按列拆分,而建议的重复按行拆分文件
  • 请编辑 Q 以包含文件的整体大小。 MB? GB?另外,为了一般知识,800,000列带有什么样的数据?!祝你好运。
  • 无论如何这可能会很慢。您当前的方法仅使用它读取的每个文件的 0.0125%,从而导致大量冗余读取。另一种方法读取文件一次,但保持 8000 个文件打开以写入每个部分行。这可能是不可行的,尽管您可能可以增加操作系统一次允许的打开文件的数量。 (另一种方法是在写入文件时打开和关闭文件,可能非常慢。)这也不是您想在 shell 中做的事情。

标签: bash unix awk cut


【解决方案1】:

试试这个 awk 脚本:

awk -v cols=100 '{ 
     f = 1 
     for (i = 1; i <= NF; i++) {
       printf "%s%s", $i, (i % cols && i < NF ? OFS : ORS) > (FILENAME "." f)
       f=int(i/cols)+1
     }
  }' largefile

我希望它比问题中的 shell 脚本更快。

【讨论】:

  • @123 在我的系统上,/proc/sys/fs/file-max 的值为 1216186,足以处理将 800000 列拆分为 100 个块所需的文件
  • @par:我不认为有,因为每个线程都需要整个文件才能提取它需要的列...
  • 我认为/proc/sys/fs/file-max系统范围 限制,而限制每个进程ulimit -n 报告,通常较低比这种情况下需要的 8000 个打开文件(没有 close 调用)。如果您有足够新的 Linux 发行版(例如 Ubuntu 16.04),您可以将限制增加到 8000(例如,Ubuntu 14.04 的上限为 4096)。
  • @mklement0:我用一个包含 800000 列的文件测试了它到 8000 个文件中,它似乎工作......ulimit -n 虽然只返回 1024。我的 awk 版本是GNU Awk 4.1.3。让我们看看它是否适用于 OP 的设置...
  • 这个脚本已经运行了 17 个小时,并且似乎在合理的时间内完成了这项工作。输出文件目前有 40,000 行中的大约 17,000 行。
猜你喜欢
  • 2015-08-22
  • 2013-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
相关资源
最近更新 更多