【问题标题】:split STDIN to multiple files (and compress them if possible)将 STDIN 拆分为多个文件(并尽可能压缩它们)
【发布时间】:2014-03-25 08:06:30
【问题描述】:

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

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

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

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

我可以:

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

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

【问题讨论】:

  • 有什么原因不能将split -l-l 参数的偶数一起使用?见:man split
  • @PaulR 有 - 我需要首先将整个数据流实例化为磁盘上的物理文件。

标签: file split stdin gnu-parallel


【解决方案1】:

GNU Parallel 可以将标准输入分割成记录块。这会将标准输入分成 50 MB 的块,每条记录为 2 行。每个chunk都会传给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)。你命令行 会爱你的。

【讨论】:

  • 好的,看起来很不错。但是有一个问题 - 此处使用并行作为一种解决方法,因此它宁愿拆分数据流,而不是同时运行所有这些压缩作业。就我而言,这有点令人担忧,因为我正在运行的机器规格较低。这是否仅限于一次不超过一到两个下游作业?
  • GNU Parallel 确实并行运行所有作业。它默认为每个 CPU 核心 1 个作业。观看介绍视频并通过教程了解如何更改默认设置。
  • 我收到了这条消息:parallel:警告:您正在使用--tollef。如果事情很奇怪,请使用--gnu。并行:警告:--tollef 已过时,将停用 20140222。并行:警告:请参阅:lists.gnu.org/archive/html/parallel/2013-02/msg00018.html /bin/bash:-c:选项需要参数
  • 您是否被stackoverflow.com/questions/16448887/… 击中如果是这样:向您的发行版维护者投诉。
  • 好的,添加了--gnu,现在收到这条消息parallel: Warning: No more processes: Decreasing number of running jobs to 1. Raising ulimit -u may help. 我称之为并行:parallel --gnu -l2 --pipe -j 1 --block 30m gzip ">"{#}.gz,它产生的文件很少,但一段时间后停止。该命令仍会运行,但会连续打印相同的警告。我已经尝试过了,我设置的块越大,它停止的越快......有什么想法吗?
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多