一、本文主要時針對while for select循環結果的特殊用法進行講解。
1、while循環的特殊用法
while read line ;do
循環體
done < /path/from/somefile
功能:依次從輸入重定向的文件中讀取每一行的內容復制給變量line,然后我們可以在循環體中執行對$line的操作,
應用舉例:掃描/etc/passwd文件每一行,如發現GECOS字段為空,則填充用戶名和單位電話為62985600,并提示該用戶的GECOS信息修改成功
#!/bin/bash # while read line do zhushi=`echo $line | cut -d: -f5` userName=`echo $line | cut -d: -f1` if [[ -z $zhushi ]];then chfn -f $userName $userName &> /dev/null chfn -p 62985600 $userName &> /dev/null echo "$userName :信息修改成功" fi done < /testdir/passwd
2、for循環的特殊用法
for ((i=1;i<100;i++))
do
循環體
done
注意:此處for循環的使用類似與c語言的語法,但是不同的是此處需要的是雙括號。
3、select循環的特殊用法
select 變量 in 參數…
do
循環體命令
done
功能:將多個參數依次付給變量,并在屏幕上依次按照編號從1-n把參數顯示出來,并根據選擇的編號,來選擇指定的參數,通常我們配合case 變量 in 來使用,因為select 是個死循環,因此需要借助break或者exit退出循環體,且可以省略in 參數,此時使用位置參數,PS3 可以定義選擇提示符,用戶輸入編號被保存在內置變量REPLY中。
應用舉例:可以參照下面服務腳本/root/bin/testsrv.sh
二、函數的用法
函數也由多條命令堆積組合在一起組成,我們可以將一些簡單的,需要重復使用的命令組合起來寫成函數,然后直接調用即可,這樣避免了,我們重復編寫代碼,可提高效率。
腳本也是有多個命令堆積組合而成,那么他們有什么區別呢?當我們在一個腳本中調用一個腳本時,我們相當于又重新開啟了一個子shell,當我們定義一個函數并調用該函數時,相當于之當前shell中運行的,在當前shell中定義的變量,可以在函數中調用和訪問的,且函數不能獨立運行,必須調用時才能執行,在函數中定義變量最好定義局部變量,避免與腳本中的命令相同的本地變量發生沖突。
定義函數:
語法1:
function f_name {
…函數體…
}
語法2:
f_name() {
…函數體…
}
定義一個函數,在一個文件中定義一個文件不一定必須時.sh結尾的 只要是文本文件即可,然后寫一個腳本,然后調用該函數
函數的定義和使用:
可以在交互環境下定義函數
可以將函數放在腳本中作為它的一部分,直接調用函數名,即可執行函數內部的代碼
可放在只包含函數的單獨文件中,通過source filename 就可以將函數讀到指定的shell中,便于后續我們調用一些功能模塊
函數的生命周期:被調用時創建,返回時終止
函數有兩種返回值:
使用echo或printf命令的輸出結果
函數體中調用命令的輸出結果
函數的退出狀態碼:
默認取決于函數中執行的最后一條命令的退出狀態碼
自定義退出狀態碼,其格式:
return 從函數中返回,用最后狀態命令決定返回值
return 0 無錯返回
return 1-255 有錯返回
—-等同于腳本中的break功能
當我們在命令行中定義了一個命令時,可以通過set命令查看該函數,也可通過unset 函數名 取消該函數。
在腳本中定義函數時,必須要在引用腳本之前定義函數,否則會由于查找不到函數體,而報錯。
函數也可以接受位置變量
函數的遞歸:(自己調用自己)
函數直接或間接引用自身
應用舉例:n!=n(n-1)(n-2)…1
#!/bin/bash # fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; then echo 1 #當$1=1時fun函數通過echo輸出的結果 else echo $[$1*$(fact $[$1-1])] fi } fact 5 每次輸出調用函數fact 知道等$=1 才會有輸出結果
1、寫個腳本:
*
***
******
********
#!/bin/bash # read -p "please input the longs:" long for hang in `seq 1 $long`;do spaceNum=$[long-hang] xingNum=$[hang*2-1] for spacenum in `seq $spaceNum`;do echo -n " " done for xingnum in `seq $xingNum`;do echo -n "*" done echo done
root@cenots6.8 /testdir # ./jinzita.sh please input the longs:4 * *** ***** *******
2、用until循環實現國際象棋棋盤
declare -i hang=1 until [ $hang -gt 8 ];do lie=1 until [ $lie -gt 8 ];do z=$[lie%2] if [ $z -eq 0 ];then [[ $hang%2 -eq 0 ]] && echo -ne "\033[43m" "" "\033[0m" || echo -ne "\033[41m" "" "\033[0m" else [[ $hang%2 -eq 0 ]] && echo -ne "\033[41m" "" "\033[0m" || echo -ne "\033[43m" "" "\033[0m" fi let lie++ done echo let hang++ done
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為當前腳本名
#!/bin/bash # baseName=$(basename $0|cut -d"." -f1) fileName=/var/lock/subsys$baseName PS3="請輸入您要選擇的編號:" select menu in start stop restart status do case $menu in start) if [ -f $fileName ];then echo "功能已經啟動,如需重新啟動,請選擇 restart " else touch $fileName echo "啟動成功" fi ;; stop) if [ -f $fileName ];then rm -rf $fileName echo "停止完成" else echo "該功能已經停止,無需再次停止" fi ;; restart) rm -rf $fileName echo "停止完成" touch $fileName echo "啟動成功" ;; status) [ -f $fileName ] && echo "$baseName is running..." || echo "$baseName is stoped..." ;; *) echo "您輸入的信息有誤" exit 1 ;; esac done
root@cenots6.8 /testdir # ./testsrv.sh 1) start 2) stop 3) restart 4) status 請輸入您要選擇的編號:1 啟動成功 請輸入您要選擇的編號:1 功能已經啟動,如需重新啟動,請選擇 restart 請輸入您要選擇的編號:2 停止完成 請輸入您要選擇的編號:2 該功能已經停止,無需再次停止 請輸入您要選擇的編號:3 停止完成 啟動成功 請輸入您要選擇的編號:4 testsrv is running... 請輸入您要選擇的編號: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/ld
linux-x86-64.so.2
(5)每次復制完成一個命令后,不要退出,而是提示用戶鍵入新的要復制的命
令,并重復完成上述功能;直到用戶輸入quit退出
#!/bin/bash read -p "請輸入一個可執行的命令:" Cmd [ -z $Cmd ] && echo "輸入信息不能為空" && exit 1 destDir=/mnt/sysroot [ -d $destDir ] || mkdir $destDir while [[ $Cmd != quit ]]; do cmdDir=`which $Cmd` #取得命令二進制路徑 libDir=$(ldd `which cat` | sed -n "3p"|tr -d [[:space:]] | sed -r 's@(^/.*)\(.*\)$@\1@g') #取得庫文件的路徑 cmddirName=`dirname $destDir$cmdDir` #取得命令的路徑名 mkdir -p $cmddirName #創建目錄 cp -r $cmdDir $destDir$cmdDir #復制二進制文件到目標目錄中 echo "復制$destDir$cmdDir 完成" libdirName=`dirname $destDir$libDir` mkdir -p $libdirName cp -r $libDir $destDir$libDir echo "復制$destDir$libDir 完成" read -p "請重新輸入新的要復制的命令:" Cmd [ -z $Cmd ] && echo "輸入信息不能為空" && exit 1 done
root@cenots6.8 /testdir # ./copycmd.sh 請輸入一個可執行的命令:cut 復制/mnt/sysroot/bin/cut 完成 復制/mnt/sysroot/lib64/ld-linux-x86-64.so.2 完成 請重新輸入新的要復制的命令:getent 復制/mnt/sysroot/usr/bin/getent 完成 復制/mnt/sysroot/lib64/ld-linux-x86-64.so.2 完成 請重新輸入新的要復制的命令:quit root@cenots6.8 /testdir # root@cenots6.8 /testdir # /mnt/sysroot/bin/c cat cut root@cenots6.8 /testdir # /mnt/sysroot/bin/c cat cut root@cenots6.8 /testdir # /mnt/sysroot/bin/cut -d":" -f1 /etc/passwd root bin daemon
3、寫一個函數實現兩個數字做為參數,返回最大值
#!/bin/bash # function max(){ [ $1 -lt $2 ] && max=$2 && echo "最大值為:$2" } max $1 $2
root@cenots6.8 /testdir # ./fun3.sh 1 3 最大值為:3
4、寫一個函數實現數字的加減乘除運算,例如輸入 1 + 2,將得出正確結果
#!/bin/bash # function jia(){ let Sum=$1+$2 echo "和為:$Sum" } function jian(){ let Cha=$1-$2 echo "差為:$Cha" } function cheng(){ let Ji=$1*$2 echo "乘積為:$Ji" } function chu(){ let Shang=$1/$2 echo "商為:$Shang" }
#!/bin/bash source testfun.sh jia $1 $2 jian $1 $2 cheng $1 $2 chu $1 $2
root@cenots6.8 /testdir # ./testfuns.sh 9 3 和為:12 差為:6 乘積為:27 商為:3
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階斐波那契數列
#!/bin/bash # function feibonaqie() { if [ $1 -eq 0 ];then echo 0 elif [ $1 -eq 1 ];then echo 1 else echo $[$1+`feibonaqie $[$1-1]`+`feibonaqie $[$-2]`] fi } feibonaqie $1
root@cenots6.8 /testdir # ./feibonaqie.sh 3 6
6、漢諾塔(又稱河內塔)問題是源于印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。利用函數,實現
原創文章,作者:Naruto,如若轉載,請注明出處:http://www.www58058.com/38199