unix - 按行拆分一个巨大的 .gz 文件

too*_*oop 18 linux unix bash shell perl

我确定有人有以下需求,按行拆分巨大的 .gz 文件的快速方法是什么?底层文本文件有 1.2 亿行。我没有足够的磁盘空间来一次对整个文件进行压缩,所以我想知道是否有人知道可以将文件(.gz 或内部 .txt)拆分为 3x 40mn 行文件的 bash/perl 脚本或工具. 即调用它像:

    bash splitter.sh hugefile.txt.gz 4000000 1
 would get lines 1 to 40 mn    
    bash splitter.sh hugefile.txt.gz 4000000 2
would get lines 40mn to 80 mn
    bash splitter.sh hugefile.txt.gz 4000000 3
would get lines 80mn to 120 mn
Run Code Online (Sandbox Code Playgroud)

也许是在做一系列这些解决方案,或者 gunzip -c 需要足够的空间来解压缩整个文件(即原始问题): gunzip -c hugefile.txt.gz | 头 4000000

注意:我无法获得额外的磁盘。

谢谢!

小智 25

要拆分的管道使用 gunzip -c 或 zcat 打开文件

gunzip -c bigfile.gz | split -l 400000
Run Code Online (Sandbox Code Playgroud)

向 split 命令添加输出规范。

  • 这比公认的答案更有效,除非您只需要分割块的一小部分。请点赞。 (3认同)

sle*_*ske 11

如何做到最好取决于您想要什么:

  • 您想提取大文件的单个部分吗?
  • 或者您想一次性创建所有部件?

如果你想有一个文件的单一部分,你的想法用gunziphead是正确的。您可以使用:

gunzip -c hugefile.txt.gz | head -n 4000000
Run Code Online (Sandbox Code Playgroud)

这将在标准输出上输出前 4000000 行 - 您可能想要附加另一个管道来实际处理数据。

要获得其他部分,你会使用的组合headtail,如:

gunzip -c hugefile.txt.gz | head -n 8000000 |tail -n 4000000
Run Code Online (Sandbox Code Playgroud)

得到第二个块。

可能正在做一系列这些解决方案,或者 gunzip -c 需要足够的空间来解压缩整个文件

不,gunzip -c不需要任何磁盘空间 - 它在内存中完成所有操作,然后将其流式传输到标准输出。


如果您想一次性创建所有部件,使用单个命令创建所有部件会更有效,因为这样输入文件只会被读取一次。一个好的解决方案是使用split; 有关详细信息,请参阅 jim mcnamara 的回答。

  • @AloisMahdal:实际上,这将是一个很好的单独问题:-)。简短版本:`gzip` 不知道限制(来自不同的进程)。如果使用 `head`,`head` 会在接收到足够的信息后退出,并且会传播到 `gzip`(通过 SIGPIPE,参见维基百科)。对于 `tail` 这是不可能的,所以是的,`gzip` 将解压缩所有内容。 (3认同)

小智 7

当您处理(不可重绕)流时,您将需要使用尾部的“+N”形式来获取从第 N 行开始的行。

zcat hugefile.txt.gz | head -n 40000000
zcat hugefile.txt.gz | tail -n +40000001 | head -n 40000000
zcat hugefile.txt.gz | tail -n +80000001 | head -n 40000000
Run Code Online (Sandbox Code Playgroud)