如何在不创建子shell的情况下将命令输出存储在变量中[Bas​​h <v4]

Luc*_*mon 15 bash variable-assignment subshell

ksh有一个非常有趣的构造来做到这一点,详细解答如下:https://stackoverflow.com/a/11172617/636849

从Bash 4.0开始,有一个内置的mapfile内置命令可以解决这个问题:http: //www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html

但奇怪的是,它似乎不适用于进程替换:

foo () { echo ${BASH_SUBSHELL}; }
mapfile -t foo_output <(foo) # FAIL: hang forever here
subshell_depth=${foo_output[0]} # should be 0
Run Code Online (Sandbox Code Playgroud)

但是如何在Bash v3.2中做到这一点?

Dig*_*uma 15

这是另一种方法,这是不同的,它保证单独的答案.我认为这个方法是无子shell和bash子进程免费的:

ubuntu@ubuntu:~$ bar () { echo "$BASH_SUBSHELL $BASHPID"; }
ubuntu@ubuntu:~$ bar
0 8215
ubuntu@ubuntu:~$ mkfifo /tmp/myfifo
ubuntu@ubuntu:~$ exec 3<> /tmp/myfifo
ubuntu@ubuntu:~$ unlink /tmp/myfifo
ubuntu@ubuntu:~$ bar 1>&3
ubuntu@ubuntu:~$ read -u3 a
ubuntu@ubuntu:~$ echo $a
0 8215
ubuntu@ubuntu:~$ exec 3>&-
ubuntu@ubuntu:~$
Run Code Online (Sandbox Code Playgroud)

这里的技巧是使用execFD在读写模式下打开FIFO,这似乎具有使FIFO无阻塞的副作用.然后,您可以将命令重定向到FD而不阻塞它,然后读取FD.

请注意,FIFO将是一个有限大小的缓冲区,可能大约为4K,因此如果您的命令产生的输出多于此值,它将再次阻塞.

  • 哇,虚拟FD/FIFO技巧真棒!是的它看起来像是诀窍.你甚至可以定义一个"assign"函数:`assign(){local var = $ 1; 转移; "$ @">/tmp/myfifo; 读$ {var} </ tmp/myfifo; }`.我测试过,它有效:`foo(){local b; 分配b吧; echo $ b; }` (4认同)

yat*_*sek 6

在研究如何将任何“打印”命令的输出捕获到变量中时,经常会出现这个问题。因此,对于任何寻找它的人来说,这是可能的(自 bash v3.1.0 起):

printf -v VARIABLE_NAME "whatever you need here: %s" $ID

如果您调整脚本以提高速度,那么您可以使用在函数末尾设置某些全局变量的模式,而不仅仅是“回显”它 - 小心使用它,它有时被批评为导致难以维护代码。