在昨天花了很长时间尝试重定向stdout
到stdin
之后,我最终采用了以下方法。这不是很好,但我认为我更喜欢它而不是命名管道/fifo 解决方案。
read | { P0 | ... | P(n-1); } >/dev/fd/0
是将管道序列作为一个整体的{ ... } >/dev/fd/0
标准输出重定向到标准输入(即,它将 P(n-1) 的输出重定向到 P0 的输入)。使用>&0
或类似的东西不起作用;这可能是因为 bash 假定0
它是只读的,而它不介意写入/dev/fd/0
.
初始read
-pipe 是必要的,因为没有它,输入和输出文件描述符都是相同的 pts 设备(至少在我的系统上)并且重定向无效。(pts 设备不能作为管道工作;写入它会将内容显示在您的屏幕上。)通过使输入{ ... }
成为普通管道,重定向具有所需的效果。
用我的calc
/square
例子来说明:
function calc() {
# calculate sum of squares of numbers 0,..,10
sum=0
for ((i=0; i<10; i++)); do
echo $i # "request" the square of i
read ii # read the square of i
echo "got $ii" >&2 # debug message
let sum=$sum+$ii
done
echo "sum $sum" >&2 # output result to stderr
}
function square() {
# square numbers
read j # receive first "request"
while [ "$j" != "" ]; do
let jj=$j*$j
echo "square($j) = $jj" >&2 # debug message
echo $jj # send square
read j # receive next "request"
done
}
read | { calc | square; } >/dev/fd/0
运行上面的代码会得到以下输出:
square(0) = 0
got 0
square(1) = 1
got 1
square(2) = 4
got 4
square(3) = 9
got 9
square(4) = 16
got 16
square(5) = 25
got 25
square(6) = 36
got 36
square(7) = 49
got 49
square(8) = 64
got 64
square(9) = 81
got 81
sum 285
当然,这种方法有点hack。特别是该read
部分具有不希望的副作用:“真实”管道循环的终止不会导致整体终止。我想不出比read
您似乎只能通过尝试向其写入内容来确定管道循环已终止更好的事情了。