这是我能想到的——它有点乱,但是foo
在顶级 shell 上下文中运行,并且它的输出在a
顶级 shell 上下文中的变量中提供:
#!/bin/bash
foo () { echo ${BASH_SUBSHELL}; }
mkfifo /tmp/fifo{1,2}
{
# block, then read everything in fifo1 into the buffer array
i=0
while IFS='' read -r ln; do
buf[$((i++))]="$ln"
done < /tmp/fifo1
# then write everything in the buffer array to fifo2
for i in ${!buf[@]}; do
printf "%s\n" "${buf[$i]}"
done > /tmp/fifo2
} &
foo > /tmp/fifo1
read a < /tmp/fifo2
echo $a
rm /tmp/fifo{1,2}
这当然假设了两件事:
我测试了它在这些bash版本中的工作:
- 3.00.15(1)-release (x86_64-redhat-linux-gnu)
- 3.2.48(1)-release (x86_64-apple-darwin12)
- 4.2.25(1)-release (x86_64-pc-linux-gnu)
附录
我不确定mapfile
bash 4.x 中的方法是否符合您的要求,因为进程替换<()
会创建一个全新的 bash 进程(尽管不是该 bash 进程中的 bash 子shell):
$ bar () { echo "$BASH_SUBSHELL $BASHPID"; }
$ bar
0 2636
$ mapfile -t bar_output < <(bar)
$ echo ${bar_output[0]}
0 60780
$
所以虽然$BASH_SUBSHELL
这里是0,是因为它在进程替换中处于新shell进程60780的顶层。