分割大的gz文件并保留行数

3
我有一个较大的 .gz 文件(2.1G),我想要将它加载到 R 中,但是文件太大了,我必须将其分成几个部分,并在重新组合之前逐个加载每个部分。然而,我在分割文件时遇到了困难,因为我无法保留数据结构。该文件本身除了前两行外,是一个 56318 x 9592 的矩阵,其中包含非同质条目。
我使用的是 Ubuntu 16.04。首先,我尝试使用终端中的 split 命令,如此链接所建议的 (https://askubuntu.com/questions/54579/how-to-split-larger-files-into-smaller-parts?rq=1)。
$ split --lines=10000 "originalFile.gct.gz" "originalFile.gct.gz.part-"

这样做会创建比我预期更多的文件(因为我的矩阵有57000行,我希望输出6个文件,每个文件大小为10000行)。当我读取其中一个文件并调查其维度时,我看到每个文件都是一个62x9592的矩阵,表明所有列都被保留,但我得到的行数远少于我所希望的。此外,在读取时,我遇到了一个指定文件结尾意外的错误。我的想法是它没有按照我想要的方式读入。
我在这里找到了两个可能的替代方案-https://superuser.com/questions/381394/unix-split-a-huge-gz-file-by-line 特别地,我尝试使用gunzip传递不同的参数,并将输出传递给split(假设压缩文件是导致不一致行尾的原因)。我尝试了:
$ zcat originalFile.gct.gz  | split -l 10000 "originalFile.gct.gz" "originalFile.gct.gz.part-"

但是,我按照这种方法最终得到的分割结果与之前完全相同。我在将“zcat”替换为“gunzip -c”时也遇到了同样的问题,应该是将未压缩的输出发送到了分割命令。
该链接上的另一个答案建议使用类似于zcat的head或tail进行流式处理。
$ zcat originalFile.gct.gz | head -n 10000 >> "originalFile.gct.gz.1"

使用zcat命令,这个效果非常完美,正是我想要的。输出结果的维度为10000x9592,因此这是最理想的解决方案。需要注意的一点是,此输出结果是一个ASCII文本文件而不是压缩文件,但我完全可以接受。

然而,我希望能够将文件分割成10000行一组,并生成另外的输出文件。对于这种特殊情况,手动创建6个输出文件不是很麻烦,但我有数十个类似的文件,其中一些文件的大小超过10gb。因此我的问题是,如何使用split命令来分割未压缩的文件的前10000行并输出它们,自动更新后缀以生成新文件?基本上,我想要从"head"命令得到的输出结果,但使用"split"命令可以在整个文件上执行。


当文件被压缩时,原始数据的结构完全不可见。如果您希望按数据逻辑分割文件,则需要在压缩之前将其拆分。 - Barmar
@Barmar 这里的问题是我已经收到了这些压缩文件。我希望能够解压它们(而不改变原始文件),然后拆分输出,而不是相反。 - cnolte
你的第一个命令基本上是丢弃了zcat的输出,而split直接从文件中读取压缩数据。在你的解决方案中,“-”表示“从标准输入读取”,因此现在split将从zcat通过管道写入的数据中读取... - guido
4个回答

3
这是我的解决方案,最终为我所接受。
$ zcat originalFile.gct.gz | split -l 10000 - "originalFile.gtc.gz-"

如Guido在评论中提到的,我的原始命令为

$ zcat originalFile.gct.gz | split -l 10000 "originalFile.gct.gz" "originalFile.gct.gz.part-"

我之前没有利用 zcat 的输出,而是再次从压缩的数据中读取。通过在 split 参数后面加上“-”,我能够将 zcat 的标准输出传递给 split,现在管道作用与我的预期相符。


0
如果基于文件内容进行分割适用于您,请尝试:
zcat originalFile.gct.gz | awk -F$',' '{print $0 | "gzip > /tmp/name_"$1".gct.gz";}'
我的文件示例行是:2014,丹尼尔,2,1,2,3
因此,我正在使用第一列的年份将文件拆分。

0
如果基于文件内容进行分割对您有用。请尝试:
zcat originalFile.gct.gz | awk -F$',' '{print $0 | "gzip > /tmp/file_"$1".gct.gz";}'

我的文件中的一个示例行是:

2014,daniel,2,1,2,3

所以我正在使用变量$1来拆分年份(第一列)的文件

得到并输出:

/tmp/file_2014.gct.gz
/tmp/file_2015.gct.gz
/tmp/file_2016.gct.gz
/tmp/file_2017.gct.gz
/tmp/file_2018.gct.gz

0

当您想更好地控制拆分时,可以使用awk。 您提到前两行是特殊的。 尝试类似以下的内容

zcat originalFile.gct.gz | 
   awk 'BEGIN {j=1} NR<3 {next} {i++} i%5==0 {j++} {print > "originalFile.gct.part"j }'

当您想要压缩输出文件时,请修改awk命令:让它print完成的文件并使用xargs将它们gzip。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接