如何等待 Bash 中子 shell 的结果?

How to wait for results from a subshell in Bash?

我正在 Bash 中编写一个辅助函数,其任务是从 STDIN 中读取一些值(每行一个,如 ls -1 中),然后要求用户以交互方式选择一个.以前,我会使用 dmenu,但我想让它更健壮,并为不存在 X11 的情况提供支持。我也不想依赖某些外部工具,所以我决定将 shell 内置 select 作为我的后备机制。我写了以下函数:

function menu-selector {
    if ! xhost &> /dev/null; then
        cat | dmenu -l 10
    else
        select choice in $(cat); do
            echo $choice
            break
        done
    fi
}

现在,当我在管道中使用 menu-selector 时,两个分支都工作正常,例如:

ls -1 | menu-selector

在这两种情况下,都会调用适当的机制(dmenuselect),并且所选值由函数返回。 当我想在 subshell 中的某处使用我的函数时,麻烦就开始了。假设我现在想要这样的东西:

my_dir=$(ls -1 | menu-selector)
echo $my_dir

在 X11 的情况下 dmenu 弹出并等待我的操作,在这之后所选的值被传回我的代码并被打印出来。但是当我选择 no-X11 选项时,select 打印所有选项,而不是等待我的选择 returns 一个空值。这里有什么区别,更重要的是,我怎样才能使 select 以相同的方式工作,即阻止我的脚本执行,直到它得到我的回答。我的猜测是,不同之处在于两种情况使用的 IO 设备 - dmenu 使用 X root window 和 select 使用 STDIN/OUT,可能在 sub 中被不同对待shell.

这是因为您的菜单功能的子 shell 运行 的标准输入充满了 ls -1 的输出,所以 select 没有任何可读的内容。

尝试使用参数而不是标准输入来提供选项,这样您就不会混淆选项和选择:

function menu-selector {
    if ! xhost &> /dev/null; then
        echo "$@" | dmenu -l 10
    else
        select choice in "$@"; do
            echo $choice
            break
        done
    fi
}

并像

一样使用它
response=$(menu-selector $(ls -1))