是否可以使用 select 命令格式化 STDERR 以获得更好看的菜单?
我有一个简单的选择
select oChoice in $(<tempMenu.menu) ; do
case "$oChoice" in
*)
break
;;
esac
done
我尝试过这样的技巧:
exec 3>&1
select ...
...
done 2>&1 1>&3 | sed 's/^/NICE OUTPUT /'
但我不能使用转义序列(即颜色),例如
...
done 22>&1 1>&3 | sed 's/^/\033[1;33m\033[44mNICE OUTPUT /'
or
done 22>&1 1>&3 | sed 's/^/\\033[1;33m\\033[44mNICE OUTPUT /'
转义序列没有转义,而且 STDOUT 也被更改,因为我也定制了 PS3。
PS3="$(print \\n\\r)# $(print "\\033[1;33m\\033[44m")"$QUESTION"$(print "\\033[0m\\033[1;1m\\033[44m") `tput sc` $(print "")
#$(print "")
# $(print "")
# Status: $status $(print "")
# $(print "")
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `tput rc` "
据我所理解 (在屏幕上仅显示 stderr,但将 stdout 和 stderr 写入文件)我无法将 STDERR 与 STDOUT 分开,那么,是否有更智能的方法来仅使用 STDOUT 创建基于动态文本的菜单? (或解决我的问题的其他方法)
答案1
重新审视一个老问题以提供一个更少的努力执行。事实上,两个问题合二为一:
a)STDERR
在select
命令中处理
select
b) 更改命令中显示的项目的外观
替代方法已经得到解决——即不使用该select
命令的解决方案。所以我不会走这条路。
该select
命令非常方便,因为它会自动处理选项的列布局,基本上您所要做的就是案例处理。所以而不是有点重新发明轮子对于许多简单的情况来说,它可以是一个很好的解决方案。
a) 处理STDERR
您已经有了原始问题中的解决方案:重定向STDERR
到STDOUT
.
select choice in ...; do
...
done 2>&1
两个文件句柄都提供相同的功能,因此恕我直言,没有理由摆弄这个。使用STDERR
forselect
实际上是一个好主意,因为您不会破坏您的内容,STDOUT
并且可以将其用于其他目的,例如重定向。
select
b) 更改命令中显示的项目的外观
解决方案为提高如果您采用以下语法,那么这里的输出也非常简单:
select choice in $(...); do
...
done
用于$(...)
执行任何操作化妆品的select items
。
例如,您可以在 ANSI 终端上对它们进行着色:
$(for i in *; do print "\[E31m$i\E[0m"; done)
或调用着色函数(在其他情况下可重用):
function colourise_diritems {
typeset dir=$1 item
for item in $dir/*; do
if [[ -d $item ]]; then print "\E[31m$i\E[0m"
elif [[ -f $item ]]; then print "\E[32m$item\E[0m"
...
fi
done
}
select choice in $(colourise_diritems $PWD); do
...
done
显然,如果您向项目添加标记,则必须在使用结果之前清理结果;在上面的示例中,在使用 selected 之前choice
,您必须执行类似的操作
choice=${choice#\E[+([^m]*)m}
choice=${choice%\E[+([^m]*)m}
删除 ANSI 序列。
笔记:使用 ANSI 序列可能很棘手,需要进一步测试。
答案2
另一种方法是避免选择并制作菜单。为每个菜单选项(action1.sh,xxx.sh和passwords.sh)制作一个shell脚本,在menu.cfg中配置它们:
1 action1 Do action 1
2 xxx Another nice item for you
3 passwords Very dangerous
并使用读取 menu.cfg 的脚本启动菜单
#!/bin/ksh
formatmenu()
{
if [ $# -eq 2 ]
then
printf "%d) %s\n" ${1} "$2"
else
printf " %s\n" "${1}"
fi
}
showMenu()
{
echo "Enter 0 to stop or choose beneath."
cat menu.cfg|while read option proces description
do
formatmenu ${option} ${proces}
formatmenu "${description}"
done
}
getAction()
{
showMenu
while [ ${CHOICE} -eq -1 ]
do
read CHOICE?"Please enter a digit: "
if [[ ${CHOICE} != +([0-9]) ]]
then
CHOICE=-1
echo "Invalid, please enter a digit."
fi
done
}
performAction()
{
if [ ${CHOICE} -eq 0 ]
then
return
fi
process=$(grep "^${CHOICE} " menu.cfg | cut -d\ -f2)
echo "===${process}.sh==="
. ${process}.sh
}
# Start
export CHOICE=-1
getAction
echo choice=${CHOICE}
performAction
exit 0