前言
创建交互式shell脚本最常用的方法是使用菜单。提供各种选项可以帮助脚本用户了解脚本能做什么,不能做什么;通常菜单脚本会清空显示区域,然后显示可用的选项列表。本文给大家详细介绍了shell创建文本菜单与窗口部件的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
创建文本菜单
创建交互式shell脚本最常用的方法是使用菜单,它提供了各种选项帮助脚本用户了解脚本能做到的和不能做的。
shell脚本菜单的核心是case命令,该命令会根据用户在菜单上的选择来执行特定命令。
下面我们逐步了解和创建基于菜单的shell脚本的步骤。
创建菜单布局
第一步是决定在菜单上显示哪些元素以及想要显示的布局方式。
在创建菜单前,通常先清空显示器上已有的内容。这样能在干净的,没有干扰的环境中显示菜单了。
clear命令使用当前终端的terminfo数据来清理出现在屏幕上的文字。运行clear命令后可以使用echo命令显示菜单元素。
默认,echo命令只显示可打印的文本字符。而在创建菜单时一些非文本字符也非常有用,比如制表符和换行符。我们需要添加-e选项使得echo命令能解析包含在其中的非文本字符。
例如,
wsx@wsx:~/tmp$ echo -e "1./tDisplay disk space"1. Display disk space
这对于格式化菜单项布局非常方便,只需要几个echo命令就可以创建一个还不错的菜单。
clearechoecho -e "/t/t/tSys Admin Menu/n"echo -e "/t1. Display disk space"echo -e "/t2. Display logged on users"echo -e "/t3. Display memory usage"echo -e "/t0. Exit menu/n/n"echo -en "/t/tEnter an option: "
最后一行-en选项去掉末尾换行符使得菜单更专业点,光标会在行尾等待用户输入。
创建菜单的最后一步是获取用户输入。这一步用read命令。因为我们只期望用户使用单字符输入,在命令加-n选项进行限定。这样用户只需要输入一个数字,不用摁回车键。
read -n 1 option
创建菜单函数
shell脚本菜单选项作为一组独立的函数实现起来更为容易。要做到这一点,你要为每个菜单项创建独立的shell函数。第一步是决定你希望脚本执行那些功能,然后将这些功能以函数的形式放在代码中。
通常我们会为还没有实现的函数先创建一个桩函数,它是一个控函数,或者只有一个echo语句,说明最终这里需要什么内容。
function diskspace { clear echo "This is where the diskspace commands will do"}
这允许菜单在我实现某个函数时仍然能正常操作。不需要我们写出所有函数之后才能让菜单投入使用。函数从clear命令开始,这样我们就能在一个干净的屏幕上执行该函数,不会收到原先菜单的干扰。
另外,将菜单布局本身作为一个函数来创建有利于菜单制作。
function menu { clear echo echo -e "/t/t/tSys Admin Menu/n" echo -e "/t1. Display disk space" echo -e "/t2. Display logged on users" echo -e "/t3. Display memory usage" echo -e "/t0. Exit menu/n/n" echo -en "/t/tEnter an option: " read -n 1 option}
这样我们能在任何时候调用该函数以此重现菜单。
添加菜单逻辑
下一步我们需要创建程序逻辑将菜单布局和函数结合起来。这需要使用case命令。
case命令应该根据菜单中输入的字符来调用相应的函数,用case命令字符星号来处理所有不正确的菜单项。
下面展示了典型菜单的case用法:
menucase $option in0) break ;;1) diskspace ;;2) whoseon ;;3) memusage ;;*) clear echo "Sorry, wrong selection";;esac
这里首先调用menu函数清空屏幕并显示菜单。menu函数中的read命令会一直等待,知道用户在键盘上键入一个字符。然后case命令会接管余下的处理过程,基于字符调用相应的函数。
整合shell脚本菜单
现在让我们将前面的步骤全部组合起来,看看它们是如何协作的。
这是一个完整的菜单脚本例子:
wsx@wsx:~/tmp$ cat test14#!/bin/bash# simple script menufunction diskspace { clear df -k}function whoseon { clear who}function memusage { clear cat /proc/meminfo}function menu { clear echo echo -e "/t/t/tSys Admin Menu/n" echo -e "/t1. Display disk space" echo -e "/t2. Display logged on users" echo -e "/t3. Display memory usage" echo -e "/t0. Exit menu/n/n" echo -en "/t/tEnter an option: " read -n 1 option}while [ 1 ]do menu case $option in 0) break ;; 1) diskspace ;; 2) whoseon ;; 3) memusage ;; *) clear echo "Sorry, wrong selection" ;; esac echo -en "/n/n/t/t/tHit any key to continue" read -n 1 linedoneclear
使用:
Sys Admin Menu 1. Display disk space 2. Display logged on users 3. Display memory usage 0. Exit menu Enter an option:
输入1:
文件系统 1K-块 已用 可用 已用% 挂载点udev 4006080 0 4006080 0% /devtmpfs 807220 81004 726216 11% /run/dev/sda4 305650672 14226064 275828680 5% /tmpfs 4036100 1724 4034376 1% /dev/shmtmpfs 5120 4 5116 1% /run/locktmpfs 4036100 0 4036100 0% /sys/fs/cgroup/dev/sda3 524272 4684 519588 1% /boot/efitmpfs 807220 52 807168 1% /run/user/1000tmpfs 807220 16 807204 1% /run/user/125/dev/sda2 421886972 23340376 398546596 6% /media/wsx/存储 Hit any key to continue
其他都可以自己测试一下,我就不赘言了。
使用select命令
select命令只需要一条命令就可以创建出菜单,然后获取输入的答案并自动处理。
命令格式如下:
select variable in listdo commandsdone
list参数是由空格分隔的文本选项列表,这些列表构成了整个菜单。select命令会将每个列表项显示成一个带编号的选项,然后为选项显示一个由PS3环境变量定义的特殊提示符。
wsx@wsx:~/tmp$ cat smenu1 #!/bin/bash# using select in the menufunction diskspace { clear df -k}function whoseon { clear who}function memusage { clear cat /proc/meminfo}PS3="Enter an option: "select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"do case $option in "Exit program") break ;; "Display disk space") diskspace ;; "Display logged on users") memusage ;; "Display memory usage") memusage ;; *) clear echo "Sorry, wrong selection";; esacdoneclear
运行会自动生成如下菜单项:
wsx@wsx:~/tmp$ ./smenu1 1) Display disk space 3) Display memory usage2) Display logged on users 4) Exit programEnter an option:
在使用select命令时,记住存储在变量中的结果值是整个文本字符串而不是跟菜单项相关联的数字。文本字符串是要在case语句中比较的内容。
制作窗口
dialog包能够用ANSI转义控制字符在文本环境中创建标准的窗口对话框。我们可以将这些对话框融入自己的shell脚本中,借此与用户进行交互。这部分我们来学习如何使用dialog包。
安装:
sudo apt-get install dialog
dialog包
dialog包使用命令行参数来决定生成哪种窗口部件(widget)。部件是dialog包中窗口元素的术语。
部件 | 描述 |
---|---|
calendar | 提供选择日期的日历 |
checklist | 显示多个选项(其中每个选项都能打开或关闭) |
form | 构建一个带有标签以及文本字段(可以填写内容)的表单 |
fselect | 提供一个文件选择窗口来浏览选择文件 |
gauge | 显示完成的百分比进度条 |
infobox | 显示一条消息,但不用等待回应 |
inputbox | 提供一个输入文本用的文本表单 |
inputmenu | 提供一个可编辑的菜单 |
menu | 显示可选择的一系列选项 |
msgbox | 显示一条消息,并要求用户选择OK按钮 |
pause | 显示一个进度条来显示暂定期间的状态 |
passwordbox | 显示一个文本框,但会隐藏输入的文本 |
passwordform | 显示一个带标签的隐藏文本字段的表单 |
radiolist | 提供一组菜单选项,但只能选择其中一个 |
tailbox | 用tail命令在滚动窗口中显示文件的内容 |
tailboxbg | 跟tailbox一样,但是在后台模式中运行 |
textbox | 在滚动窗口中显示文件的内容 |
timebox | 提供一个选择小时、分钟和秒数的窗口 |
yesno | 提供一条带有Yes和No按钮的简单消息 |
如上表所见,我们可以选择很多不同的部件。只需要多花点功夫就可以让脚本看起来更专业。
要在命令行上指定某个特定的部件,需要使用双破折线格式:
dialog --widget parameters
其中widget是上表中某个特定的部件,parameters定义了部件窗口的大小以及部件需要的文本。
每个dialog部件都提供了两种形式的输出:
可以通过dialog命令的退出状态码来确定用户选择的按钮。如果选择了Yes或OK按钮,命令会返回状态码0。如果选择了Cancer或No按钮,命令会返回状态码1。可用标准的$?变量来确定dialog部件具体选择了哪个按钮。
如果部件返回了数据,dialog命令会将数据发送到STDERR。我们可以用标准的bash shell方法将其重定向到另一个文件或文件描述符中。
dialog --inputbox "Enter your age:" 10 20 2>age.txt
这条命令将文本框输入的文本重定向到age.txt文本中。
msgbox部件
msgbox部件是对话框中最常见的类型。它会在窗口中显示一条简单的信息,直到用户点击OK后消失。
使用格式:
dialog --msgbox text height width
text参数是要在窗口显示的字符串,height与width参数设定自动换行的窗口大小。如果想要在窗口加一个标题,可以使用--title参数,后接作为标题的文本。
例子:
dialog --title Testing --msgbox "This is a test" 10 20
输入命令后,消息框会显示在终端上。如果你的终端仿真器支持鼠标,可以单击OK来关闭对话框,也可以按下回车键。
yesno部件
该部件在窗口底部生成两个按钮:一个是Yes,一个是No。用户可以用鼠标、制表符或者键盘方向键来切换按钮。选择按钮则使用空格或者回车键。
下面是一个例子:
wsx@wsx:~$ dialog --title "Please answer" --yesno "Is this thing on?" 10 20# 中间终端有输出wsx@wsx:~$ echo $?0
dialog命令的退出状态码会根据用户选择的按钮来设置。选择No返回1,选择Yes就是0。
inputbox部件
inputbox部件提供了一个简单的文本框区域来输入文本字符串,dialog会将它传到STDERR,我们需要重定向获得输入。inputbox提供了两个按钮:OK和Cancel。如果选择了OK,命令退出状态码为0,否则为1。
wsx@wsx:~/tmp$ dialog --inputbox "Enter your age:" 10 20 2>age.txtwsx@wsx:~/tmp$ cat age.txt 24
如果你自己运行过的话就会注意到该值后面没有换行符,这让我们能够轻松将文本内容重定向到脚本变量中,以获得用户输入的值。
textbox部件
textbox部件是在窗口中显示大量信息的极佳办法。它会生成一个滚动窗口来显示由参数所指定的文件中的文本。
wsx@wsx:~/tmp$ dialog --textbox /etc/passwd 15 45
/etc/passwd文件内容显示在可滚动的文本窗口中,可以用方向键来左右或上下滚动显示文件的内容。窗口底部的行会显示当前查看文本处于文件中的哪个位置(百分比)。文本框只包含一个用来选择退出部件的Exit按钮。
menu部件
我们可以用这个部件来创建之前(上一篇笔记)中制作的文本菜单的窗口版本。只要为每个选项提供一个选择标号和文本就行。
wsx@wsx:~/tmp$ dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 2 "Display users" 3 "Display memory usage" 4 "Exit" 2>test.txt
第一个参数定义了菜单的标题,之后的两个参数定义了菜单窗口的高和宽,而第四个参数则定义了在窗口中一次显示的菜单项总数。如果存在更多选择,则有滚动条。
菜单项必须使用菜单对:第一个元素是用来选择菜单项的标号(必须唯一);第二个元素是菜单中使用的文本。
dialog命令会将选定(鼠标点击或回车键或选择OK)的菜单项文本发送到STDERR。
fselect部件
该部件在处理文件名时非常方便。不用强制用户键入文件名,我们就可以用fselect部件来浏览文件的位置并选择文件。
使用格式:
wsx@wsx:~/tmp$ dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt
第一个参数是窗口使用的其实目录位置。fselect部件窗口由左侧的目录列表、右侧的文件列表和含有当前选定的文件或目录的简单文本框组成。可以手动在文本框键入文件名,或者用目录和文件列表来选定(使用空格键选定)。
dialog选项
除了标准部件,dialog还有大量定制的选项。前面我们使用的title就是一个。
下面显示了命令可用的选项:
选项 | 描述 |
---|---|