用bash异步消耗管道

MrM*_*ter 6 shell pipe producer-consumer

我有这样的bash脚本

data_generator_that_never_guits | while read data 
do
 an_expensive_process_with data
done
Run Code Online (Sandbox Code Playgroud)

第一个过程连续生成事件(以不规则的间隔),需要在它们可用时进行处理.这个脚本的一个问题是read on消耗了一行输出; 由于处理非常昂贵,我希望它能够使用当前可用的所有数据.另一方面,如果有新数据可用,则必须立即开始处理.简而言之,我想做这样的事情

data_generator_that_never_guits | while read_all_available data 
do
 an_expensive_process_with data
done
Run Code Online (Sandbox Code Playgroud)

如果没有数据可供使用,命令read_all_available将等待,或者将所有当前可用数据复制到变量.如果数据不是由实线组成,那就完全没了问题.基本上,我正在寻找一个读取模拟,它将读取整个管道缓冲区而不是从管道中读取一行.

对于你们之间的好奇,我有一个需要触发源文件重建的构建脚本的问题的背景会发生变化.我想避免经常触发重建.请不要建议我使用grunt,gulp或其他可用的构建系统,它们不能很好地用于我的目的.

谢谢!

MrM*_*ter 1

我想在我更好地了解子 shell 的工作原理之后我已经找到了解决方案。该脚本似乎可以满足我的需要:

\n\n
data_generator_that_never_guits | while true \ndo\n # wait until next element becomes available\n read LINE\n # consume any remaining elements \xe2\x80\x94 a small timeout ensures that \n # rapidly fired events are batched together\n while read -t 1 LINE; do true; done\n # the data buffer is empty, launch the process\n an_expensive_process\ndone\n
Run Code Online (Sandbox Code Playgroud)\n\n

可以将所有读取行收集到一个批次中,但我此时并不真正关心它们的内容,所以我没有费心去弄清楚那部分:)

\n\n

添加于 2014 年 9 月 25 日

\n\n

这是最后一个子例程,以防有一天它对某人有用:

\n\n
flushpipe() {\n # wait until the next line becomes available\n read -d "" buffer\n # consume any remaining elements \xe2\x80\x94 a small timeout ensures that \n  # rapidly fired events are batched together\n while read -d "" -t 1 line; do buffer="$buffer\\n$line"; done\n echo $buffer   \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

像这样使用:

\n\n
data_generator_that_never_guits | while true \ndo\n # wait until data becomes available\n data=$(flushpipe)\n # the data buffer is empty, launch the process\n an_expensive_process_with data\ndone\n
Run Code Online (Sandbox Code Playgroud)\n