bash腳本編程之select語句、函數

概述

    承接上篇,繼續介紹一下另一個循環語句select,還有腳本中函數的相關內容,分為三個部分:

        1、select語句的介紹和效果演示

        2、腳本函數詳解

        3、函數效果舉例

第一章    select語句的介紹和效果演示

    1、select 循環與菜單格式

        select VAR in LIST;do

            循環體命令

        done

        select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示 PS3 提示符,等待用戶輸入

        用戶輸入菜單列表中的某個數字,執行相應的命令

        用戶輸入被保存在內置變量 REPLY 中

    2、select 與 case

        select 是個無限循環,因此要記住用 break 命令退出循環,或用 exit 命令終止腳本。也可以按 ctrl+c退出循環

        select 經常和 case 聯合使用

        與 for 循環類似,可以省略 in list , 此時使用位置參量

    3、selcet應用舉例

    blob.png blob.png

    blob.png blob.png

    blob.png blob.png

    4、補充:腳本執行時幾種執行方式的區別

        .和source來執行腳本與bash 和給腳本執行權限執行的區別:

            . 和source執行腳本時:沒有開子進程執行腳本,相當于直接在shell里面運行腳本里面的語句,故運行完腳本,腳本里面的變量在shell里依然有效

            bash或執行權限執行腳本:開了個子進程執行腳本,故腳本里面定義的變量,無法在shell里面繼續生效

第二章    腳本中函數詳解

    1、函數的基本概念

        函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程。

        它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分。

        注意:定義函數的代碼段不會自動執行,在調用時才執行

        

    2、函數和shell程序比較相似,區別在于:

        Shell程序在子Shell中運行

        而Shell函數在當前Shell中運行。因此在當前Shell中,函數可以對shell中變量進行修改

        函數在腳本中,相當于在腳本中插入了一段代碼,所以函數并不是在腳本的shell中又開一個子shell執行函數,而是跟腳本shell在同一個shell中

    3、函數的定義:

        語法一:

             function FUNCTION_NAME {

                  函數體

                }

        語法二:

              FUNCTION_NAME() {

                  函數體

                }

 

        函數的定義位置:
            可在交互式環境下定義函數
            可將函數放在腳本文件中作為它的一部分
            可放在只包含函數的單獨文件中

    4、函數的調用

        在代碼中給定函數名即可,函數名出現的任何位置,在代碼執行時,都會被自動替換為函數代碼

        函數的生命周期:被調用時創建,返回時終止

        可以將經常使用的函數存入函數文件,然后將函數文件載入shell。文件名可任意選取,但最好與相關任務有某種聯系。例如: functions.main,一旦函數文件載入shell,就可以在命令行或腳本中調用函數。可以使用set命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數。若要改動函數,首先用unset命令從shell中刪除函數。改動完畢后,再重新載入此文件

        載入文件的方式:.  FILENAME或source FILENAME

    5、函數的返回值

        函數有兩種返回值:
            函數的執行結果返回值:

            <1> 使用echo或printf命令進行輸出

            <2> 函數體中調用命令的輸出結果
        函數的退出狀態碼:

            <1> 默認取決于函數中執行的最后一條命令的退出狀態碼

            <2> 自定義退出狀態碼, 其格式為:

                return 從函數中返回,用最后狀態命令決定返回值

                    return 0 無錯誤返回。

                    return 1-255 有錯誤返回

        return其功能與腳本中exit的功能類似,在函數運行的任何地方,出現return即代表函數終止,即便return的位置不是最后一行,也會退出整個函數,功能與腳本的exit一樣,腳本中一旦遇到exit,就退出腳本的運行

    6、刪除函數

        unset命令完成此功能.命令格式為:unset FUNCTION_NAME

    7、函數中的參數

        函數可以接受參數:
            傳遞參數給函數:調用函數時,在函數名后面以空白分隔,給定參數列表即可;例如  FUNCTION_NAME arg1 arg2 …
        在函數體中當中,可使用$1, $2, …調用這些參數;還可以使用$@, $*, $#等特殊變量

    8、函數中的變量

        變量作用域:
            環境變量:當前shell和子shell有效
            本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范圍是當前shell腳本程序文件,包括腳本中的函數。
            局部變量:函數的生命周期;函數結束時變量被自動銷毀

        

            定義局部變量的方法:在函數體中,使用local VAR=VALUE

                這樣定義之后,該變量的作用范圍就僅僅在函數體內部生效,函數結束,則變量不會影響后續腳本中變量的運行

        注意:如果函數中有局部變量,如果其名稱同本地變量, 使用局部變量

    9、函數的遞歸

        函數的遞歸:函數直接或間接調用自身

         例如:數學中的階乘

              N!=N*(N-1)!=N*(N-1)*(N-2)!=…

         這樣就可以用函數的遞歸進行計算

         jc() {

              if [ $1 -eq 0 -o $1 -eq 1 ];then

                  echo 1

              else 

                  echo "$[$1*`jc $[$1-1]`]"

              fi

         }

         例如:斐波那契數列

         1,1,2,3,5,8,13,21…

         第一個值為1,第二個值為1,隨后的每一個值都為其前兩個數字之和

         求斐波那契數列的第N個數字是多少:(N-1)+(N-2)

         fblq() {

              if [ $1 -eq 1 -o $1 -eq 2 -o $1 ];then

                  echo 1

              else

                  echo "$[`fblq $[$1-1]`+`fblq $[$1-2]`]"

             fi

         }

第三章    函數效果舉例

    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_NAMEis running…”如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示“SCRIPT_NAME is stopped…”其中:SCRIPT_NAME為當前腳本名

        (7)在所有模式下禁止啟動該服務,可用chkconfig 和 service命令管理

    #!/bin/bash    
    # Autor: nwc
    # Version: 2.0
    # CreateTime: 2016-08-19
    # Description:
    # 關于第7條的實現,考慮可以將腳本放到/etc/init.d目錄下,在腳本開頭注釋段標明“# chkconfig:運行級別  啟動優先級  關閉優先級”    # 然后運行chkconfig  --add 腳本名 --level 指定哪些級別開機啟動
    
    FILE=/tmp/$0
    
    START() {
            if [ -f $FILE ];then
                    echo "$0 has been start"        
            else
                    touch $FILE && echo "Start success" || echo "Start fail"
            fi
    }
    
    STOP() {
            if [ -f $FILE ];then
                    rm -rf $FILE && echo "Stop success" || echo "Stop fail"
            else
                    echo "$0 has been stopped"
            fi
    }
    
    RESTART() {
            STOP
            START
    }
    
    STATUS() {
            [ -f $FILE ] && echo "$0 is running..." || echo "$0 is stopped..."
    }
    
    
    read -p "Please input you choice start|stop|restart|status:  " CH
    
    case $CH in
    start)
            START
    ;;
    
    stop)
            STOP
    ;;
    
    restart)
            RESTART
    ;;
    
    status)
            STATUS
    ;;
    
    *)
            echo "bad choice..."
    ;;
    esac

    執行效果如下:

    blob.png

    blob.png

    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    
    # Autor: nwc
    # Version: 2.0
    # CreateTime: 2016-08-19
    # Description:
    
    CMDCP() {
            DIR=`dirname $CmdPath`
            if [ -d ${LuJing}${DIR} ] ;then
                    cp $CmdPath ${LuJing}${DIR} && echo "cp $CMD success" || echo "cp $CMD fail"
            else
                    mkdir -p ${LuJing}${DIR}
                    cp $CmdPath ${LuJing}${DIR} && echo "cp $CMD success" || echo "cp $CMD fail"
            fi    
    }
    
    CMDLIBCP() {   
            for i in ${LibCmd} ; do
                    LIBDIR=`dirname $i`
                    if [ -d ${LuJing}${LIBDIR} ];then
                            cp $i ${LuJing}${LIBDIR} && echo "cp $i success" || echo "cp $i fail" 
                    else
                            mkdir -p ${LuJing}${LIBDIR}
                            cp $i ${LuJing}${LIBDIR} && echo "cp $i success" || echo "cp $i fail" 
                    fi
            done
    }
    
    
    while true;do
         read -p "Input a exec program name like ls/cat... q for quit  " CMD
            case $CMD in
            q)
                    echo "exit..."
                    exit
            ;;
            *)
                    if which --skip-alias $CMD &>/dev/null  && [[ $CMD != "q" ]]; then
                            CmdPath=`which --skip-alias $CMD`
                            LibCmd=`ldd $CmdPath|grep -o -E "/[^[:space:]]+"`
                            LuJing=/tmp/command
                            CMDCP
                            CMDLIBCP
                    else
                             echo "you input is not a right command"
                                    continue
                    fi
            ;;
            esac
    done

      執行效果如下:

    blob.png

    blob.png  

    blob.png

    blob.png

    blob.png

    blob.png

    

原創文章,作者:M20-1倪文超,如若轉載,請注明出處:http://www.www58058.com/37714

(0)
M20-1倪文超M20-1倪文超
上一篇 2016-08-21
下一篇 2016-08-21

相關推薦

  • inode 是什么及絕對路徑和相對路徑和一些目錄相關命令總結

    inode是什么          每個分區又分兩個區,元數據區和數據區。     元數據區主要存儲文件的權限,屬主屬組,時間戳,文件的存儲位置指針….就如一本書有目錄頁和內容頁一樣,目錄頁上的記錄的是內容的頁數,可以通過目錄頁的頁數直接…

    Linux干貨 2016-08-02
  • Linux之DNS服務

    DNS服務 DNS: Domain Name Service,協議(C/S, 53/udp, 53/tcp)應用層協議 BIND:BekerleyInternatName Domain, ISC (www.isc.org) 本地名稱解析配置文件:hosts     /etc/hosts   &nbs…

    Linux干貨 2016-10-05
  • 計劃任務與啟動流程

    一、任務計劃 未來的某時間點執行一次任務:    at:在指定的時間執行任務    batch:系統自行選擇空閑時間去執行此處指定的任務周期性運行某任務:    cron:在指定的時間執行任務 1、at任務at [option] TIME  常用選項:&nbs…

    Linux干貨 2016-09-13
  • N26第一周博客作業

    1.       計算機的組成及其功能 計算機由以下5部分組成: 控制器:控制器是計算機的中樞神經,功能是對程序規定的控制信息進行解釋,根據其要求進行控制,調度程序、數據、地址,協調計算機各個部分工作及內存與外存的訪問等。 運算器:運算器功能主要是對數據進行各種算術和邏輯運算,即對數據進行加工處理。…

    Linux干貨 2016-12-28
  • Linux基礎-用戶管理相關操作-week 4

    1.復制/etc/skel 目錄為/home/tuser1,要求/home/tuser1及其內部文件的屬組和其他用戶均沒有任何訪問權限  cp /etc/skel /home/tuser1 -rf chmod og=  /home/tuser1 -R 2.編輯/etc/group文件添加組hadoop echo hadoop:x:503 …

    Linux干貨 2016-11-21
  • Linux基礎操作-week5

    1、顯示當前系統上root、fedora或user1用戶的默認shell; 方式一: # whoami root # echo $SHELL /bin/bash 方式二: #grep user1 /etc/passwd|awk -F “:” ‘{print $7}’ /bin/bash 2、找出/etc/rc.…

    Linux干貨 2016-11-27

評論列表(1條)

  • 馬哥教育
    馬哥教育 2016-08-22 12:04

    總結的很詳細,作業也完成的很用心,關于shell腳本主要是多抽時間寫,看,學習別人的思想,只有養成了編程的思想,才能寫出優秀的代碼。

欧美性久久久久