我希望能够在现有bash管道中的进程之间管道数据。为了更好地说明我的意思,请采用这个简单的例子,我假设文件描述符3的行为类似于fifo。
seq 5 | tee >(while read num; do echo $(($num * $num)); done >&3) | paste - <(<&3 cat)
我想要输出
1 1
2 4
3 9
4 16
5 25
然后终止。理想情况下,解决方案类似于exec 3<>-
,其中bash会将文件描述符3作为读写缓冲区打开。据我所知,在bash中没有对此的支持,所以我转向this question来创建匿名管道。根据讨论,我想出了这个功能:
function temp_pipe() {
[[ "$1" =~ [3-9] ]] || return 1
PIPE_DIR="$(mktemp -d)"
PIPE="$PIPE_DIR/pipe"
mkfifo "$PIPE"
eval "exec $1<>'$PIPE'"
rm -f "$PIPE"
rmdir "$PIPE_DIR"
}
将文件描述符作为参数,并将其附加到匿名fifo。这原则上有效,但是当我写完输出信息时,我无法弄清楚如何关闭fifo。以下几乎按预期工作:
temp_pipe 3 && seq 5 | tee >(while read num; do echo $(($num * $num)); done >&3) | paste - <(<&3 cat)
因为它输出正确的结果,但粘贴保持打开,因为文件描述符3永远不会关闭。我天真地以为我可以将exec 3>&-
附加到子进程的末尾以关闭文件描述符并使所有内容按预期工作,但这不起作用。父文件描述符未关闭,因为关闭操作在子进程中运行,因此关闭对同一描述符的继承引用,而不是关闭父进程中的描述符。
我理想地寻找一种解决方案,在没有大量临时fifos或文件描述符的手动管理的情况下构建复杂流水线相对容易。