描述:
select控制語句基于Korn Shell中的控制結構
select語句首先顯示一個菜單,然后根據用戶的選擇給變量賦予相應的值,最后執行一系列命令。
語法:
select varname [ in arg…]
do
commands
done
說明:
select結構顯示arg項的菜單。加入忽略關鍵字in和參數列表,select控制語句就用位置參數來取代arg項。select的菜單格式化為在每一項前加一個數字。
select循環主要用于創建菜單,按數字順序排列的菜單項顯示在標準輸出上,并顯示PS3提示符,等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令。
用戶輸入被保存在內置變量REPLY中。
select是個無限循環,使用break命令退出循環,或用exit命令終止腳本,也可以按ctrl+c推出循環
select經常和case聯合使用
與for循環類似,可以省略in list,此時使用位置參數
示例:
#!/bin/bash PS3="Please guss which fruit I like:" select var in "apple" "pear" "orange" "peach";do if [ "$var" == "apple" ];then echo "You are right" break else echo "try again" fi done [root@localhost ~]# bash a.sh 1) apple 2) pear 3) orange 4) peach Please guss which fruit I like:2 try again Please guss which fruit I like:3 try again Please guss which fruit I like:4 try again Please guss which fruit I like:1 You are right
函數:
函數(function)是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程,
它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分
函數和shell程序的區別在于:
shell程序在子shell中運行,而shell函數在當前shell中運行。因此在當前shell中,函數可以對shell中的變量進行修改
函數由兩部分組成:函數名和函數體
語法一:
function NAME {
函數體
}
語法二:
NAME() {
函數體
}
函數的使用:
可以在交互式環境下定義函數
可將函數放在腳本文件中作為它的一部分
可放在只包含函數的單獨文件中
調用:函數只有被調用才會執行
調用:給定函數名
函數名出現的地方,會被自動替換為函數代碼
函數的生命周期:被調用時創建,返回時終止
函數的執行結果返回值:
1,使用echo或printf命令進行輸出
2,函數體調用命令的輸出結果
函數的退出狀態碼:
1,默認取決于函數最后一條命令的退出狀態碼
2,自定義退出狀態碼,其格式為:
return 從函數中返回,用最后狀態命令決定返回值
return 0 正確返回
return 1-255 有錯誤返回
交互式環境下定義和使用函數
示例:
[root@localhost ~]# dir(){ > ls -l 定義該函數后,在命令行直接鍵入dir,其顯示結果同ls -l的作用相同 > } [root@localhost ~]# dir -rw-r--r--. 1 root root 205 Aug 19 17:55 a.sh -rwxr-xr-x. 1 root root 106 Aug 12 05:42 backup.sh drwxr-xr-x. 2 root root 4096 Aug 15 06:28 bin [root@localhost ~]# unset dir 從當前系統中退出該dir函數
在腳本中定義及使用函數
函數在使用前必須定義,因此應該將函數定義放在腳本開始部分,直到shell首次發現它后才能使用
調用函數僅使用其函數名即可
示例:
[root@localhost ~]# cat func1 #!/bin/bash #func1 hello(){ echo "Hello there today's date is `date +%F`" } echo "now going to the function hello" hello echo "back from the function" [root@localhost ~]# chmod +x func1 [root@localhost ~]# ./func1 now going to the function hello Hello there today's date is 2016-08-21 back from the function
使用函數文件
可以將經常使用的函數存入函數文件,然后將函數文件載入shell
文件名可任意取,但最后與相關任務有某種聯系。例如:functions.main
一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂胹et命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數
若要改動函數,首先用unset命令從shell中刪除函數。改動完畢后,再重新載入此文件
創建函數文件:
示例:
[root@localhost ~]# cat function.main 函數文件 #!/bin/bash #functions.main findit() { if [ $# -lt 1 ];then echo "Usage:findit file" return 1 fi find / -name $1 -print }
函數文件已創建好后,要將它載入shell
定位函數文件并載入shell格式:
. filename 或 source filename (即<點> <空格> <文件名>) (這里的文件名要帶正確路徑)
使用set命令檢查函數是否已載入。set命令將在shell中顯示所有已載入的函數
[root@localhost ~]# . function.main [root@localhost ~]# set findit () { if [ $# -lt 1 ]; then echo "Usage:findit file"; return 1; fi; find / -name $1 -print } [root@localhost ~]# findit groups 執行shell函數,鍵入函數名即可 /usr/bin/groups
[root@localhost ~]# unset findit 刪除shell函數(命令格式為:unset function_name) [root@localhost ~]# set 函數findit無顯示
函數參數:
傳遞參數給函數:調用函數時,在函數名后面以空白分隔給定參數列表即可;例如:"findit a b …"
在函數體中當中,可使用$1,$2,…調用參數,還可以使用$@,$*,$#等特殊變量
函數變量:
環境變量:當前shell和子shell有效
本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范圍是當前shell腳本程序文件,包括腳本中的函數
局部變量:函數的生命周期;函數結束時變量被自動銷毀
注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量
在函數中定義局部變量的方法: local NAME=VALUE
函數遞歸示例:
[root@localhost ~]# cat fact.sh #!/bin/bash fact() { if [ $1 -eq 0 -o $1 -eq 1 ];then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact 4 [root@localhost ~]# bash -x fact.sh + fact 4 + '[' 4 -eq 0 -o 4 -eq 1 ']' ++ fact 3 ++ '[' 3 -eq 0 -o 3 -eq 1 ']' +++ fact 2 +++ '[' 2 -eq 0 -o 2 -eq 1 ']' ++++ fact 1 ++++ '[' 1 -eq 0 -o 1 -eq 1 ']' ++++ echo 1 +++ echo 2 ++ echo 6 + echo 24 24
作業:
1、寫一個服務腳本/root/bin/testsrv.sh,完成如下要求
(1) 腳本可接受參數: start, stop, restart, status
(2) 如果參數非此四者之一,提示使用格式后報錯退出
(3) 如是start:則創建/var/lock/subsys/SCRIPT_NAME, 并顯示“啟動成功”
考慮:如果事先已經啟動過一次,該如何處理?
(4) 如是stop:則刪除/var/lock/subsys/SCRIPT_NAME, 并顯示“停止完成”
考慮:如果事先已然停止過了,該如何處理?
(5) 如是restart,則先stop, 再start
考慮:如果本來沒有start,如何處理?
(6) 如是status, 則如果/var/lock/subsys/SCRIPT_NAME文件存在,則顯示
“ SCRIPT_NAME is running…”
如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示“ SCRIPT_NAME
is stopped…”
其中: SCRIPT_NAME為當前腳本名
[root@localhost function]# cat testsrv.sh #!/bin/bash fstart () { if [ -e "$1" ];then echo "Already Start" else touch $File echo "Start Successfully!" fi } fstop() { if [ -e "$1" ];then rm -f $File echo "Stop Successfully!" else echo "Already stop" fi } frestart() { if [ -e "$1" ];then fstop &> /dev/null fstart &> /dev/null echo "Restart Successfully!" else fstart &> /dev/null echo "Start Successfully!" fi } fstatus() { if [ -e "$1" ];then echo "testsrv is running" else echo "testsrv has been stop" fi } select choice in start stop restart status quit;do File=/var/lock/subsys/testsrv.sh case $choice in start) fstart $File ;; stop) fstop $File ;; restart) frestart $File ;; status) fstatus $File ;; quit) break ;; *) echo "error,please choose again" exit 2 esac done [root@localhost function]# bash testsrv.sh 1) start 2) stop 3) restart 4) status 5) quit #? 4 testsrv is running #? 3 Restart Successfully! #? 1 Already Start #? 2 Stop Successfully! #? 5
2、編寫一個腳本/root/bin/copycmd.sh
(1) 提示用戶輸入一個可執行命令名稱;
(2) 獲取此命令所依賴到的所有庫文件列表
(3) 復制命令至某目標目錄(例如/mnt/sysroot)下的對應路徑下;
如: /bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
(4) 復制此命令依賴到的所有庫文件至目標目錄下的對應路徑下:
如: /lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ldlinux-x86-64.so.2
(5)每次復制完成一個命令后,不要退出,而是提示用戶鍵入新的要復制的命
令,并重復完成上述功能;直到用戶輸入quit退出
[root@localhost ~]# cat copycmd.sh #!/bin/bash ch_root="/mnt/sysroot/" [ ! -d $ch_root ] && mkdir $ch_root bincopy() { if which $1 &>/dev/null;then local cmd_path=`which --skip-alias $1` local bin_dir=`dirname $cmd_path` [ -d ${ch_root}${bin_dir} ] || mkdir -p ${ch_root}${bin_dir} [ -f ${ch_root}${cmd_path} ] || cp $cmd_path ${ch_root}${bin_dir} return 0 else echo "Command not found" return fi } libcopy() { local lib_list=$(ldd `which --skip-alias $1` | grep -Eo '/[^[:space:]]+') for loop in $lib_list;do local lib_dir=`dirname $loop` [ -d ${ch_root}${lib_dir} ] || mkdir -p ${ch_root}${lib_dir} [ -f ${ch_root}${loop} ] || cp $loop ${ch_root}${lib_dir} done } read -p "Please input a command:" command while [ "$command" != "quit" ];do if bincopy $command;then libcopy $command fi read -p "Please input a command or quit:" command done [root@localhost ~]# ll /mnt/sysroot/lib64 -rwxr-xr-x. 1 root root 164432 Aug 23 15:28 ld-linux-x86-64.so.2 -rwxr-xr-x. 1 root root 37056 Aug 23 15:28 libacl.so.1 -rwxr-xr-x. 1 root root 19888 Aug 23 15:28 libattr.so.1 -rwxr-xr-x. 1 root root 20024 Aug 23 15:28 libcap.so.2 -rwxr-xr-x. 1 root root 2107816 Aug 23 15:28 libc.so.6 -rwxr-xr-x. 1 root root 19512 Aug 23 15:28 libdl.so.2 -rwxr-xr-x. 1 root root 153192 Aug 23 15:28 liblzma.so.5 -rwxr-xr-x. 1 root root 398272 Aug 23 15:28 libpcre.so.1 -rwxr-xr-x. 1 root root 142296 Aug 23 15:28 libpthread.so.0 -rwxr-xr-x. 1 root root 147120 Aug 23 15:28 libselinux.so.1 [root@localhost ~]# ll /mnt/sysroot/usr/bin -rwxr-xr-x. 1 root root 54048 Aug 23 15:41 cat -rwxr-xr-x. 1 root root 117616 Aug 23 15:35 ls
3、寫一個函數實現兩個數字做為參數,返回最大值
#!/bin/bash function NUMBER { if [ $1 -lt $2 ];then echo "The max number is $2" elif [ $1 -eq $2 ];then echo "The two number is equal" else echo "The max number is $1" fi } NUMBER $1 $2
[root@localhost function]# bash test3.sh 3 5 The max number is 5 [root@localhost function]# bash test3.sh 6 4 The max number is 6 [root@localhost function]# bash test3.sh 8 8 The two number is equal
4、寫一個函數實現數字的加減乘除運算,例如輸入 1 + 2,將得出正確結果
[root@localhost function]# cat test4-1.sh #!/bin/bash fjia() { sum=$[$1+$2] echo "$sum" } fjian() { sum=$[$1-$2] echo "$sum" } fcheng() { sum=$[$1*$2] echo "$sum" } fchu() { sum=$[$1/$2] echo "$sum" } read -p "please input: " a b c case $b in +) fjia $a $c ;; -) fjian $a $c ;; \*) fcheng $a $c ;; /) fchu $a $c ;; *) echo "please input correct form" exit 3 esac [root@localhost function]# bash test4-1.sh please input: 6+7 please input correct form please input: 6 + 7 13 please input: 6 - 8 -2 please input: 2 * 3 6 please input: 4 / 2 2
5、斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列: 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 ……,斐波納契數列以如下被以遞歸的方法定義: F( 0) =0, F( 1) =1, F( n) =F(n-1)+F(n-2)(n≥2)
寫一個函數,求n階斐波那契數列
[root@localhost function]# cat test5-1.sh #!/bin/bash ftzsl() { if [ $1 -eq 0 ];then echo "0" elif [ $1 -eq 1 ];then echo "1" else echo "$[$(ftzsl $[$1-1])+$(ftzsl $[$1-2])]" fi } read -p "please input a number: " n ftzsl $n [root@localhost function]# bash test5-1.sh please input a number: 5 5 please input a number: 6 8
6、漢諾塔(又稱河內塔)問題是源于印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間
一次只能移動一個圓盤。利用函數,實現N片盤的漢諾塔的移動步驟
[root@localhost function]# cat test6.sh #!/bin/bash fpan() { if [ $1 -eq 1 ];then echo "$2 ==> $4" else fpan $[$1-1] $2 $4 $3 echo "$2 ==> $4" fpan $[$1-1] $3 $2 $4 fi } fpan $1 a b c [root@localhost function]# bash test6.sh 2 a ==> b a ==> c b ==> c
原創文章,作者:pingsky,如若轉載,請注明出處:http://www.www58058.com/38881