【发布时间】:2018-03-22 10:42:39
【问题描述】:
假设我有流式文本数据进入我的 Bash 脚本,每行一条记录,我想在每一行附加该行的一些函数并将其吐到 stdout:
record1 record1 fn(record1)
record2 -> record2 fn(record2)
... ...
这相对容易做到,比如 Awk。但是,假设我应用于输入数据的函数在应用于流数据时效率要高出几个数量级(而且我有很多,因此绝对不能选择逐行 Awk 处理)。这是我想出的解决方案:
input="$(mktemp)"
trap "rm -rf ${input}" EXIT
cat > "${input}"
paste "${input}" <(some_function "${input}")
这通过将stdin 重定向到一个临时文件(cat 行),然后使用进程替换将文件paste 合并在一起来实现。但是,这对我来说似乎有点混乱(例如,UUOC),我认为可能有一种“更好”的方式来使用exec(用于重定向)和tee,但我不太确定如何.
这可以做得更好吗?
【问题讨论】:
-
fn(recordX)是用recordX调用fn的结果 -
假设即使您可以一次性从标准输入读取多行,但您希望按记录写入输出(每行唯一),对吗?在这种情况下,肯定需要一次处理一行?你不觉得
-
是的,从这个意义上说,但我的观点是,如果应用于整个流而不是逐行调用,我上面的
some_function会快得多。为了更具体:some_function这里是从输入中提取一个字段,然后对其进行 base64 解码,然后根据某些标准对其进行分类。如果逐行运行,base64 解码步骤是瓶颈;有点技巧,它可以在流数据上运行以获得相同的结果,并且它可以在几分钟而不是几小时/几天内运行......我上面的解决方案非常有效,我只是想知道是否有更好/更好的方法。 -
是的,完全同意您在读取方面的观点,但关键是您的写入逻辑在每一行中都是唯一的,对吧?您不能在每个唯一行上进行批量写入吗?有意义吗?
-
是的,这是有道理的。我的解决方案计算
fn(record1)到fn(recordN)的值,然后paste将它们重新组合在一起。 POSIX 流/缓冲的性质使它们保持同步,这实际上是“批量写入”,但我看不出这一点与我的问题的相关性。
标签: bash redirect stream pipe tee