腳本之循環的特殊用法及函數的使用

一、本文主要時針對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

(1)
NarutoNaruto
上一篇 2016-08-21
下一篇 2016-08-21

相關推薦

  • sed編輯器使用

     簡述       sed編輯器被稱作流編輯器,和普通的交互式文本編輯器恰好相反。在交互式文本編輯器中(比如vim), 你可以用鍵盤命令來交互式地插入、刪除或替換數據中的文本。流編輯器則會在編輯器處理數據之前基于預先 提供的一組規則來編輯數據流。sed編輯器可以根據命令來處理數據流中的數據,這些命令…

    2017-06-19
  • 馬哥教育網絡班20期+第二周課程練習

    1、Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示。 文件管理有 cp, mv, rm  復制命令:cp [root@ddwhost ~]# cp /etc/magic /tmp/         cp&n…

    Linux干貨 2016-06-23
  • N25-第五周作業

    第五周 1、顯示/boot/grub/grub.conf中以至少一個空白字符開頭的行; [root@zf ~]# grep -E "^[[:space:]]+[[:alnum:]]+" /boot/grub/grub.conf     &n…

    Linux干貨 2016-12-26
  • MySQL or MariaDB 簡介

    DBMS:數據庫管理系統 RDBMS:關系型數據庫管理系統    總之:他們都是一個數據管理程序;大多都是CS架構,都有專門的通信協議進行數據交換 關系模型:               表(行或者列):二維關系 設計范式:       &…

    Linux干貨 2017-01-12
  • 設計模式 ( 十二 ) 職責鏈模式(Chain of Responsibility)(對象行為

    1.概述        你去政府部門求人辦事過嗎?有時候你會遇到過官員踢球推責,你的問題在我這里能解決就解決,不能解決就推卸給另外個一個部門(對象)。至于到底誰來解決這個問題呢?政府部門就是為了可以避免屁民的請求與官員之間耦合在一起,讓多個(部門)對象都有可能接收請求,將這些(部門)對象連接成一條鏈,并且沿著這條鏈傳遞…

    Linux干貨 2015-07-15
欧美性久久久久