Shell 使用bash异步使用管道

Shell 使用bash异步使用管道,shell,pipe,producer-consumer,Shell,Pipe,Producer Consumer,我有这样一个bash脚本 data_generator_that_never_guits | while read data do an_expensive_process_with data done data_generator_that_never_guits | while read_all_available data do an_expensive_process_with data done 第一个过程连续生成事件(以不规则的间隔),这些事件需要在可用时进行处理。这个脚

我有这样一个bash脚本

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

data_generator_that_never_guits | while read data 
do
 an_expensive_process_with data
done
data_generator_that_never_guits | while read_all_available data 
do
 an_expensive_process_with data
done
其中,如果没有可供使用的数据,则read_all_available命令将等待,或者将所有当前可用的数据复制到变量中。如果数据不是由完整的行组成,这是非常好的。基本上,我正在寻找一种读取模拟,它将读取整个管道缓冲区,而不是仅读取管道中的一行

对于你们当中好奇的人来说,问题的背景是我有一个构建脚本,它需要在源文件更改时触发重建。我希望避免太频繁地触发重建。请不要建议我使用grunt、gulp或其他可用的构建系统,它们不适合我的目的


谢谢

read-n4096-t1
这样的东西可能会起作用,或者
read-t0
加上额外的逻辑。有关详细信息,请参阅Bash参考手册。否则,您可能必须从Bash迁移到例如Perl。

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

data_generator_that_never_guits | while true 
do
 # wait until next element becomes available
 read LINE
 # consume any remaining elements — a small timeout ensures that 
 # rapidly fired events are batched together
 while read -t 1 LINE; do true; done
 # the data buffer is empty, launch the process
 an_expensive_process
done
可以将所有的读取行收集到一个批次中,但此时我并不真正关心它们的内容,所以我没有费心弄清楚这一部分:)

于2014年9月25日添加

下面是最后一个子程序,以防有一天它对某人有用:

flushpipe() {
 # wait until the next line becomes available
 read -d "" buffer
 # consume any remaining elements — a small timeout ensures that 
  # rapidly fired events are batched together
 while read -d "" -t 1 line; do buffer="$buffer\n$line"; done
 echo $buffer   
}
要像这样使用:

data_generator_that_never_guits | while true 
do
 # wait until data becomes available
 data=$(flushpipe)
 # the data buffer is empty, launch the process
 an_expensive_process_with data
done

谢谢你的回答,塞巴斯蒂安。不过,我不太确定这在我的情况下应该如何运作。我的印象是,如果没有产生输入,读取将失败,从而终止循环?在任何情况下,我都想等待输入(如果必须的话,可以无限期地等待)。只是在一些数据出现在管道中之后,我想清除整个管道。我已经有了一个运行良好的Python版本,但是它太长太麻烦了,因为它必须执行一堆shell命令。