如何等待 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
在这两种情况下,都会调用适当的机制(dmenu
或 select
),并且所选值由函数返回。
当我想在 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))
我正在 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
在这两种情况下,都会调用适当的机制(dmenu
或 select
),并且所选值由函数返回。
当我想在 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))