shell下的菜单-1

        三种生成菜单的方式,C编写的菜单解析程序、dialog工具、select语法。前两种方式是基于curses库的实现,可以处理光标移动,第三种方式由ksh或bash所提供的select菜单方式实现,不支持光标移动。

        第一种方式由两部分组成,C语言编写的菜单解析程序和shell编写的菜单处理程序。

菜单解析程序getkey.c:

/********************************************************
*程序功能:根据传入的菜单文件和坐标起始位置,显示菜单并
*	   获取选中条目,返回选中位置,该程序配合shell编写
*          通用界面,菜单项开始的1. 2. 3. 表示快捷键,
*	   只支持单屏显示,暂不支持多屏显示.
*程序参数:argv[1] 全路径菜单文件名 argv[2] 起始行位置
*	   argv[3] 起始列位置       argv[4] 上次选中菜单项
*程序返回:返回的是选中的菜单编号,正确的菜单编号从1开始,
	   0表示程序错误退出。
*程序注意:该程序违反一般UNIX程序的返回惯例,主要是为了解决
	   shell下不能处理负数返回值的问题,0表示出错。
*********************************************************/
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         /**定义支持的菜单条数和菜单长度**/ #define MAX_ITEM_NUM 40 #define MAX_ITEM_LEN 80 /**菜单项的前缀字符个数**/ #define MENU_OPT_LEN 2 struct Menu { int beg_l;/**起始行坐标**/ int beg_c;/**起始列坐标**/ char menu_item[MAX_ITEM_NUM][MAX_ITEM_LEN];/**菜单项**/ int item;/**菜单项数目**/ int lst_sel;/**上次选择菜单项**/ }; void endscr(); int getchoice(const struct Menu* menu); int get_menu(struct Menu* menu, char* file); void clear_all_screen(); int draw_menu(const struct Menu* menu, int selected); /**屏幕最大行坐标和列坐标**/ static int max_l=0,max_c=0; static int show_error_l=20,show_error_c=0; static int g_ret=0; int main(int argc, char *argv[]) { if(argc<5) { printf("usage:%s menu_file line col def_sel\n", argv[0]); return 0; } struct Menu stMenu; char cMenu[MAX_ITEM_NUM][MAX_ITEM_LEN]; memset(&stMenu, 0x00, sizeof(stMenu)); stMenu.beg_l=atoi(argv[2]); stMenu.beg_c=atoi(argv[3]); stMenu.lst_sel=atoi(argv[4]); initscr(); curs_set(0);/**设置光标不可见**/ getmaxyx(stdscr, max_l, max_c);/**返回的是最大行数和列数**/ max_l-=1;/**行坐标从0开始**/ max_c-=1;/**列坐标从0开始**/ if(stMenu.beg_l<0 || stMenu.beg_l>max_l) stMenu.beg_l=0; if(stMenu.beg_c<0 || stMenu.beg_c>max_c) stMenu.beg_c=0; g_ret = get_menu(&stMenu, argv[1]); if(g_ret){ mvprintw(show_error_l++, show_error_c, "Get menu error!"); endscr(); return 0; } if(stMenu.lst_sel<1 || stMenu.lst_sel>stMenu.item) stMenu.lst_sel=1; int selected = getchoice(&stMenu); curs_set(0);/**设置光标可见**/ endscr(); return selected; } int get_menu(struct Menu* menu, char* file) { if(menu==NULL||file==NULL) { clear(); mvprintw(show_error_l++, show_error_c, "Func [%s] NULL POINTER!",__func__); return 1; } char cLine[256]; memset(cLine, 0x00, sizeof(cLine)); FILE* fp=fopen(file, "r"); if(fp==NULL){ clear(); mvprintw(show_error_l++, show_error_c, "Open file [%s] error!",file); return 1; } while(fgets(cLine, sizeof(cLine), fp)) { menu->item++; if(menu->item>MAX_ITEM_NUM) { break; } strncpy(menu->menu_item[menu->item-1], cLine, sizeof(menu->menu_item[0])-1); memset(cLine, 0x00, sizeof(cLine)); } fclose(fp); return 0; } /*clear_all_screen函数*/ void clear_all_screen() { clear(); } /**0表示程序出错,>0值表示用户选择的菜单序号**/ int getchoice(const struct Menu* menu) { if(menu==NULL) { clear(); mvprintw(show_error_l++, show_error_c, "Func [%s] NULL POINTER!",__func__); return 0; } int selected=0; int key = 0; clear_all_screen(); keypad(stdscr, TRUE);/**打开功能键模式**/ cbreak(); noecho(); selected = menu->lst_sel-1;/**默认选中的菜单项**/ while(1) { if(key == KEY_UP) { /**默认可循环**/ if(selected<=0){ selected=menu->item-1; }else{ --selected; } } if(key == KEY_DOWN) { /**默认可循环**/ if(selected>=menu->item-1){ selected=0; }else{ ++selected; } }else if(key=='\n' || key==KEY_ENTER)/**通过光标选中了某个选项**/ { break; } else { for(int i=0; i 
        
          item; ++i) { if(key==menu->menu_item[i][0]) { selected=i; break; } } } g_ret=draw_menu(menu, selected); if(g_ret){ mvprintw(show_error_l++, show_error_c, "Draw menu error!"); selected=-1; break; } key = getch(); } keypad(stdscr, FALSE); nocbreak(); echo(); return selected+1; } int draw_menu(const struct Menu* menu, int selected) { if(menu==NULL) { clear(); mvprintw(show_error_l++, show_error_c, "Func [%s] NULL POINTER!",__func__); return 1; } int pos_l=menu->beg_l, pos_c=menu->beg_c; char item_opt[MENU_OPT_LEN]={0}; for(int i=0; i 
         
           item; ++i) { memset(item_opt, 0x00, sizeof(item_opt)); strncpy(item_opt, menu->menu_item[i], MENU_OPT_LEN); mvprintw(pos_l, pos_c, "%s", item_opt);/**选项a,b,c,...不高亮**/ if(i == selected){ attron(A_STANDOUT);/**设置高亮属性**/ } mvprintw(pos_l++, pos_c+strlen(item_opt), "%s", menu->menu_item[i]+strlen(item_opt));/**不包含选项a,b,c,**/ if(i == selected){ attroff(A_STANDOUT);/**关闭高亮属性**/ } } refresh(); return 0; } void endscr() { refresh(); endwin(); } 
          
         
       
      
      
     
     
    
    
   
   

       通过cc -O2 -o getkey -lcurses getkey.c编译得到getkey可执行程序,以便在菜单处理程序中使用。

shell编写的菜单处理程序:

#!/usr/bin/sh
old_stty_setting=`stty -g`
trap " stty \"$old_stty_setting\";exit 1" 1 2 15

#确认完成返回
confirm_over()
{
	echo "\033[22;0H按
   
   
    
    确认完成\c"
	read
}

#确认是否继续
confirm_ok()
{
	echo "\033[22;0H按
    
    
     
     确认执行\c"
	read
	if [ "$REPLY" = "y" ];then
		return 0
	else
		return 1
	fi
}

#选中退出选项
f0()
{
	stty "$old_stty_setting"
	exit 0
}

#选中第一个菜单
f1()
{
	clear
	if confirm_ok ;then
		#要执行的命令
		:
		clear
		confirm_over
	fi
}

#选中第二个菜单
f2()
{
	clear
	confirm_over
}

#选中第三个菜单
f3()
{
	clear
	confirm_over
}

#选中第四个菜单
f4()
{
	clear
	confirm_over
}

MENU_FILE=menu.txt

cat >$MENU_FILE <<-EOF
	1.执行批前备份
	2.执行日终程序
	3.查询日终日志
	4.查看系统状态
	q.退出菜单
EOF

#定义菜单的响应程序
set -A menu_acts f1 f2 f3 f4 f0

if [ `wc -l<$MENU_FILE` -ne $((${#menu_acts[*]})) ]
then
	echo "请检查菜单条目和响应程序是否一致!"
	exit 1
fi

while true
do
	getkey $MENU_FILE 0 0 "$ans"
	ans=$?
	#将菜单编号转换为从0开始
	m_i=$((ans-1))
	if [ $m_i -lt 0 ]
	then
		exit 1
	fi
	${menu_acts[$m_i]}
done

    
    
   
   

菜单效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值