免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 10083 | 回复: 4
打印 上一主题 下一主题

shell脚本实现的命令行交互菜单界面模板 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-06 16:18 |只看该作者 |倒序浏览
还是很久以前做过一次完整的类似工作,当时感觉shell脚本功能还很弱,转用awk,光阴流转已经忘的差不多了,最近有需要又做了一个,决定做的通用些,易维护和扩展,下面就是阶段的成果,参考了pdmenu,一个通用的配置文件导向的全屏文本菜单程序。

在脚本中通过特定的注释定义菜单,这种配置模式可以基本满足扩展维护时的便利性。

菜单定义:
定义的一菜单以注释符跟随menu开头,即# menu ...这样,后面是菜单定义项,以:分隔,完整格式如下:

# menu:【菜单完整路径,即从顶菜单项直到当前项的所有层接子项,以->分隔】:【快捷键】:【菜单显示字符串】:【菜单命令,如果是的话】

注意:
1、快捷键和显示部分是独立定义的,也就是定义者需要显式维护他们的关联,比如你希望是1作为快捷键,显示字符串可以是1、。。。,或者(1)。。。这样的形式,完全由自己喜好决定。
2、如果菜单不是命令的话,最后一项为空,保留前面的:分隔符
3、内定顶菜单路径为main,不可改变,也就是所有的菜单路径都是main->...这样的格式

代码部分:
代码很简单,一共两个函数,和一个全局变量,全局变量是为顶菜单main准备的

prepare_menu()
{
        while read line; do
                eval array=( $(echo $line | sed -n 's/[[:space:]]*#[[:space:]]*#*[[:space:]]*(menu)[[:space:]]*:[[:space:]]*(.*)[[:space:]]*:[[:space:]]*(.*)[[:space:]]*:[[:space:]]*(.*)[[:space:]]*:[[:space:]]*(.*)[[:space:]]*#*[[:space:]]*$/"1" "2" "3" "4" "5"/pg') )
                (( ${#array[@]} )) || continue
                declare -a menus=( ${array[1]//->/ } )
                declare menu="menu_${menus[0]}"
                declare title="${menus[0]}"
                for name in $(echo ${menus[@]:1}); do
                        title="${title}->${name}"
                        submenu=${menu}_${name}[0]
                        if [ -z "${!submenu}" ] ; then
                                eval ${menu}_${name}=( ${title} )
                                # eval ${menu}_${name}[4]=0
                                eval count=${$menu[4]}
                                eval $menu[$(($count+5))]=${menu}_${name}
                                eval $menu[4]=$(($count+1))
                        fi
                        menu="${menu}_${name}"
                done
                eval $menu[1]="${array[2]}"
                eval $menu[2]="${array[3]}"

                if [ -n "${array[4]}" ]; then
                        eval $menu[3]="${array[4]}"
                fi
        done < $1
}


show_menu()
{
        declare title
        declare -i count
        eval title=${$1[0]}
        eval count=${$1[4]}
       
        while : ; do
                echo
                echo "$title:"
                echo
                declare item
                for (( i=0; i<$count; i++ )); do
                        eval item=${$1[$(($i+5))]}
                        eval echo ${$item[2]}
                done
                echo
                echo -n "lease choice the function"
                if [ "$1" != "main" ]; then
                        echo -n ", [q] for return up"
                fi
                echo -n ": "
                read choice
                [[ -z "$choice" ]] && continue
                declare shortkey
                for (( i=0; i<$count; i++ )); do
                        eval item=${$1[$(($i+5))]}
                        eval shortkey=${$item[1]}
                        [[ "$choice" == "$shortkey" ]] && break
                done
                if [ "$choice" == "$shortkey" ]; then
                        declare exec
                        eval exec=${$item[3]}
                        if [ "$exec" != "" ]; then
                                echo
                                eval $exec
                                echo
                                echo -n "ress any key to continue ..."
                                read choice
                                echo
                        else
                                show_menu $item
                        fi
                elif [ "$choice" == "q" ]; then
                        return
                fi
        done       
}



declare -a menu_main=( "main" "ShortKey" "Main" "Exec" "0"


使用时,只需要两行调用就可以运行了:
prepare_menu $0
show_menu menu_main

比如在脚本里添加一下行就定义了两条主菜单下的菜单项,system和network:

# menu:main->system:11) System:
# menu:main->network:22) Network:

继续添加system下面的命令:

# menu:main->system->uptime:11) How long the system has been running (uptime):uptime
# menu:main->system->who:22) Show who is logged on and what they are doing (w):w
# menu:main->system->vmstat:33) Report virtual memory statistics (vmstat):vmstat

这里定义了三个system菜单的子项,分别调用uptime,w,vmstat

类似可以继续增加下去。

进一步的解释:

扩展性是由可配置性保证的,上面已经看到,还有一个方面就是维护的便利。
菜单命令可以是任何脚本可调用的系统命令或者函数,一般你可以在增加菜单项的同时,增加其调用的函数代码,即在菜单命令下面完成菜单的功能实现,方便以后的查找修改,例如:
# menu:main->system->uptime:11) How long the system has been running (uptime):show_uptime
show_uptime()
{
   uptime
}

如果有需要,你也可以在菜单显示项中使用命令替换技巧来动态改变其显示。
对于菜单的组织问题,则完全交给作者根据实际的运行效果来调整,也算是可见即可得吧。
最后注意在你的脚本顶部加上#!/bin/sh和执行路径定义,希望这个模板能有所帮助。

[ 本帖最后由 TiGEr.zZ 于 2009-8-6 16:33 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-08-06 22:29 |只看该作者
怎么没人理这个呢?

论坛徽章:
0
3 [报告]
发表于 2010-04-27 10:37 |只看该作者
例子看得有点模糊,不如将要生产哪些文件,运行的效果列出来。

论坛徽章:
0
4 [报告]
发表于 2010-04-27 11:05 |只看该作者
学习学习

论坛徽章:
0
5 [报告]
发表于 2010-04-27 11:43 |只看该作者
lz贴的这个怎么没法运行呢,是什么shell
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP