前言
創建交互式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就是一個。
下面顯示了命令可用的選項: