如果我无法完整提取.tar.gz存档,是否可以拆分一个巨大的文本文件(基于行数)解压缩该文件



我有一个.tar.gz文件。它包含一个 20GB 大小的文本文件,有 2050 万行。我无法将此文件作为一个整体提取并保存到磁盘。我必须执行以下任一选项:

  1. 在每个文件中指定行数(例如 100 万行),并获取 21 个文件。这将是首选选项。
  2. 根据行号提取该文件的一部分,即从1000001到2000001,以获得具有 1M 行的文件。我将不得不使用不同的参数重复此步骤 21 次,这非常糟糕。

可能吗?

这个答案 - bash:仅提取部分 tar.gz 存档 - 描述了一个不同的问题。

要从f.tar.gz中提取文件并将其拆分为文件,每个文件不超过 100 万行,请使用:

tar Oxzf f.tar.gz | split -l1000000

以上将按默认方法命名输出文件。 如果您希望将输出文件命名为 prefix.nn,其中 nn 是序列号,请使用:

tar Oxzf f.tar.gz |split -dl1000000 - prefix.

在这种方法下:

  • 原始文件永远不会写入磁盘。 tar.tar.gz文件中读取并将其内容通过管道传输到split,后者在将片段写入磁盘之前将其分成多个部分。

  • .tar.gz文件仅读取一次。

  • split ,通过其众多选择,具有很大的灵活性。

解释

对于tar命令:

  • O告诉tar将输出发送到标准输出。 这样,我们可以将其通过管道传输到split,而无需将原始文件保存在磁盘上。

  • x告诉tar提取文件(而不是创建存档)。

  • z告诉tar存档是gzip格式。 在现代焦油上,这是可选的

  • f告诉tar使用指定的文件名作为输入。

对于split命令:

  • -l告诉split拆分受行数(而不是字节)限制的文件。

  • -d告诉split对输出文件使用数字后缀。

  • -告诉split从stdin获取输入

您可以使用 tar 中的 --to-stdout(或 -O)选项将输出发送到 stdout。然后使用 sed 指定所需的行集。

#!/bin/bash
l=1
inc=1000000
p=1
while test $l -lt 21000000; do
  e=$(($l+$inc))
  tar -xfz --to-stdout myfile.tar.gz file-to-extract.txt |
      sed -n -e "$l,$e p" > part$p.txt
  l=$(($l+$inc))
  p=$(($p+1))
done

这是选项 #1 的纯 Bash 解决方案,自动将行拆分为多个输出文件。

#!/usr/bin/env bash
set -eu
filenum=1
chunksize=1000000
ii=0
while read line
do
  if [ $ii -ge $chunksize ]
  then
    ii=0
    filenum=$(($filenum + 1))
    > out/file.$filenum
  fi
  echo $line >> out/file.$filenum
  ii=$(($ii + 1))
done

这将从 stdin 中获取任何行并创建文件,例如具有前百万行的 out/file.1out/file.2具有第二百万行等。 然后,您所需要的只是将输入提供给上面的脚本,如下所示:

tar xfzO big.tar.gz | ./split.sh

这永远不会将任何中间文件保存在磁盘上,甚至保存在内存中。 它完全是一个流媒体解决方案。 这有点浪费时间,但在空间方面非常有效。 它也非常便携,应该在 Bash 以外的外壳中工作,并且在几乎没有变化的古老系统上工作。

您可以使用

sed -n 1,20p /Your/file/Path

在这里,您提到您的第一行号和最后一行号我的意思是说这可能看起来像

sed -n 1,20p /Your/file/Path >> file1

并在变量中使用起始行号和结束行号并相应地使用它。

相关内容

最新更新