我正在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
),并且函数会返回所选的值。
当我想在子shell中的某个地方使用我的函数时,麻烦就开始了。假设我现在想要这样的东西:
my_dir=$(ls -1 | menu-selector)
echo $my_dir
在X11情况下,弹出dmenu
并等待我的操作,选定的值将传递回我的代码并打印出来。但是当我选择no-X11选项时,select
会打印所有选项,但不是等待我的选择,而是返回一个空值。这里有什么区别,更重要的是,我如何让select
以相同的方式工作,即阻止执行我的脚本,直到它得到我的回答。我猜测不同之处在于两种情况下使用的IO设备 - dmenu
使用X根窗口而select
使用STDIN / OUT,可能在子shell中处理不同。
答案 0 :(得分:0)
这是因为运行菜单功能的子shell的标准输入填充了ls -1
的输出,因此select
无法读取。
尝试使用参数而不是stdin来提供选项,这样您就不会有混淆选项和选择:
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))