7

我有将数据流输出到其 STDOUT 的程序(gawk)。处理的数据实际上是 10 GB。我不想将它保存在单个文件中,而是将其拆分为多个块,并可能在保存之前对每个块应用一些额外的处理(如压缩)。

我的数据是一系列记录,我不想将记录分成两半。每条记录都匹配以下正则表达式:

^\{index.+?\}\}\n\{.+?\}$

或者为了简单起见,可以假设两行(首先是不均匀的,然后即使从流的开头编号)总是记录。

我可以吗:

  • 使用一些标准的 linux 命令通过定义块的首选大小来拆分 STDIN?不需要精确,因为记录可变大小不能保证。或者,如果定义为记录数。按大小是不可能的
  • 压缩每个块并存储在一个文件中(名称中有一些编号,如 001、002 等)

我已经意识到像GNU 并行这样的命令,csplit但不知道如何将它们组合在一起。如果上面解释的功能可以在不为其编写自定义 perl 脚本的情况下实现,那就太好了。然而,这可能是另一种最后的解决方案,但同样不确定如何最好地实施它。

4

2 回答 2

8

GNU Parallel 可以将标准输入拆分成记录块。这会将标准输入分成 50 MB 的块,每条记录为 2 行。每个块将被传递给 gzip 并压缩为名称 [chunk number].gz:

cat big | parallel -l2 --pipe --block 50m gzip ">"{#}.gz

如果你知道你的第二行永远不会以 '{index' 开头,你可以使用 '{index' 作为记录开始:

cat big | parallel --recstart '{index' --pipe --block 50m gzip ">"{#}.gz

然后,您可以通过以下方式轻松测试拆分是否正确:

parallel zcat {} \| wc -l ::: *.gz

除非您的记录长度相同,否则您可能会看到不同数量的行,但都是偶数。

观看介绍视频以进行快速介绍: https ://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

浏览本教程(man parallel_tutorial)。你的命令行会爱你。

于 2014-03-25T08:26:02.463 回答
2

您可以使用可以读取 STDIN(除了普通文件)的split实用程序(与GNU coreutils软件包一起提供,因此在目标系统上找到的机会更多),使用按行或按大小阈值并应用自定义逻辑parallel通过--filter CMD选项分块。使用详情请参考相应的手册页。

cat target | split -d -l10000 --suffix-length 5 --filter 'gzip > $FILE.gz' - prefix.

将 STDIN 拆分为 gzip 压缩的块,每个 10000 行,名称为prefix.<CHUNK_NUMBER>,其中<CHUNK_NUMBER>从 0 开始并用零填充到 5 的长度(例如000000000100002等)。也可以设置起始编号和额外后缀。

于 2018-12-05T11:27:54.370 回答