shell腳本之 select 循環菜單及 函數

select 循環與菜單

select variable in list

   do

     循環體命令

  done

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

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

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

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

select 經常和case 聯合使用

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

#!/bin/bash
select choice in 1yuan 2yuan 5yuan Quit ;do 
    case $choice in
        1yuan)
            echo "You can buy a glass of water "
            ;;  
        2yuan)
            echo "You can buy  an ice cream "
            ;;  
        5yuan)
            echo "You can buy  a chicken leg "
            echo "Choice $REPLY" 
            ;;  
        Quit)
            echo "Bye"
            break
            ;;  
        *)  
            echo "Enter error!"
            exit 2
     
    esac
done

wKioL1e4BqiilhV-AAAhaQGtGs0385.png

wKioL1e4BqjQf0gSAAAfm8B2O7Q099.png

wKiom1e4BqmQUDOOAAAffmYbBPQ578.png

函數介紹

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

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

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

  Shell程序在子Shell中運行

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

定義函數格式:

函數由兩部分組成:函數名和函數體。

語法一:

  function f_name{

    …函數體…

  }

語法二:

  function f_name(){

    …函數體…

  }

語法三:

  f_name(){

    …函數體…

  }


函數使用:

函數的定義和使用:

    可在交互式環境下定義函數

    可將函數放在腳本文件中作為它的一部分

    可放在只包含函數的單獨文件中

調用:函數只有被調用才會執行;

    調用:給定函數名

    函數名出現的地方,會被自動替換為函數代碼

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

函數返回值:

函數有兩種返回值:

  函數的執行結果返回值:

    (1) 使用echo或printf命令進行輸出

    (2) 函數體中調用命令的輸出結果

  函數的退出狀態碼:

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

    (2) 自定義退出狀態碼,其格式為:

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

        return 0 無錯誤返回。

        return 1-255 有錯誤返回


交互式環境下定義和使用函數:

示例:

$dir() {
> ls-l
> }

定義該函數后,若在$后面鍵入dir,其顯示結果同ls-l的作用相同。

    $dir

該dir函數將一直保留到用戶從系統退出,或執行了如下所示的unset命令:

    $ unsetdir

在腳本中定義及使用函數:

函數在使用前必須定義,因此應將函數定義放在腳本開始部分,直至shell首次發現它后才能使用

調用函數僅使用其函數名即可。

#!/bin/bash
#fun1

hello () {
    echo "Hello there today's date is `date +%F`"
}

echo "Now going to the funtion hello"
hello
echo "back from the function"

wKiom1e4CjGwE2WDAAAV-iXA4dU011.png


使用函數文件

1、可以將經常使用的函數存入函數文件,然后將函數文件載入shell。

2、文件名可任意選取,但最好與相關任務有某種聯系。例如:functions.main

3、一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂胹et命令查看所有定義的函   數,其輸出列表包括已經載入shell的所有函數。

4、若要改動函數,首先用unset命令從shell中刪除函數。改動完畢后,再重新載入此文件。

載入函數

函數文件已創建好后,要將它載入shell

定位函數文件并載入shell的格式:

    . filename 或source filename

   注意:此即<點> <空格> <文件名>

這里的文件名要帶正確路徑

檢查載入函數

使用set命令檢查函數是否已載入。set命令將在shell中顯示所有的載入函數。

執行函數

要執行函數,簡單地鍵入函數名即可

刪除shell函數

現在對函數做一些改動。首先刪除函數,使其對shell不可用。使用unset命令完成此功能.

命令格式為:unset function_name


函數參數:

函數可以接受參數:

    傳遞參數給函數:調用函數時,在函數名后面以空白分隔給定參數列表即可;

        例如“testfuncarg1 arg2 …”

    在函數體中當中,可使用$1, $2, …調用這些參數;還可以使用$@, $*, $#等特殊變量

函數變量

變量作用域:

  環境變量:當前shell和子shell有效

  本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范         圍是當前shell腳本程序文件,包括腳本中的函數。

  局部變量:函數的生命周期;函數結束時變量被自動銷毀

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

在函數中定義局部變量的方法:local NAME=VALUE

函數遞歸:函數直接或間接調用自身(注意遞歸層數)

遞歸實例:

階乘是基斯頓·卡曼于1808 年發明的運算符號,是數學術語,一個正整數的階乘(factorial)是所有小于及等于該數的正整數的積,并且有0的階乘為1。自然數n的階乘寫作n!。

n!=1×2×3×…×n。

階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n。

n!=n(n-1)(n-2)…1

n(n-1)! = n(n-1)(n-2)!

#!/bin/bash
jiecheng () {
    if [ $1 -eq 1 -o $1 -eq 0 ] ;then
        echo 1
    else
        echo "$[$1*$(jiecheng $[$1-1])]"
    fi  
}

read -p "計算階乘,請輸入一個正數字:" n
if [[ $n =~ ^[[:digit:]]+$ ]] ;then
    jiecheng $n
else
    echo "請輸入一個正整數!"
    exit 2
fi

wKioL1e4Dhvy_yZEAAAyuT7VXHM290.png


示例:

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為當前腳本名

#!/bin/bash
fstart () {
    if [ -e "$1"  ]; then
        echo "Already start"
    else
        touch $ff
        echo "Start Successfully!"
    fi
}

fstop () {
    if [ -e "$1" ] ; then
        rm -f $1
        echo "Stop Successfully!"
    else
        echo "Already stop"
    fi
}

frestart() {
    if [ -e "$1" ] ; then
        fstop &> /dev/null
        fstart &> /dev/null
        echo "Restart successful"
    else
        fstart &> /dev/null
        echo "start successful " 
    fi
}

fstatus () {
    if [ -e "$1" ] ;then
        echo "testsrv is runing..."
    else
        echo "testsrv is stopped..."
    fi
}

select choice in start stop restart status quit
do
    ff=/var/lock/subsys/testsrv.sh
    case $choice in
    start)
        fstart $ff
        ;;
    stop)
        fstop $ff
        ;;
    restart)
        frestart $ff
        ;;
    status)
        fstatus $ff
        ;;
    quit)
        break
        ;;
    *)
        echo "error!"
        exit 2
    esac
done

wKiom1e4EUzwMMjMAABAXX-rL3M002.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

fcopy () {
    aa=`which $1 | tail -1`
   ldd $aa 
   if [ $? -eq 0 ] ;then
    cp --parents $aa  /mnt/sysroot/ && echo "Command has been copied ! "
    ldd $aa | sed  -r  -e  "s@.*[[:space:]]+(/.*)[[:space:]].*@\1@g" -e '1d' > /testdir/copycmd 
        while read line ;do
            cp --parents $line /mnt/sysroot/ 
        done < /testdir/copycmd
     echo "Libary file has been copied !"
    fi  
}   

select choice in  run  quit ;do 
    case $choice in
    run)
        read -p "Please enter a command:" cmd 
        fcopy $cmd
        ;;  
    quit)
        echo "bye"
        exit 0
        ;;  
    *)  
        echo "error"
        exit 2
    esac
done

wKioL1e4E4Cw1a_pAACQ9pTWlrg979.png

wKioL1e4E2rBg0CWAAAuEQ38bYw113.png

3、編寫函數實現兩個數字做為參數,返回最大值

#!/bin/bash
fmax () {
    if [ $1 -lt $2 ] ;then
        echo "$2"
    else
        echo "$1"
    fi  
}
 
fmax $1 $2

wKioL1e4FDLgpW_WAAANjK0ykUc050.png

4、編寫函數實現數字的加減乘除運算,例如輸入1 + 2,,將得出正確結果

#!/bin/bash
fjia () {
    sum1=$[$1+$2]
    echo $sum1
}

fjian () {
    sum2=$[$1-$2]
    echo $sum2
}

fcheng () {
    sum3=$[$1*$2]
    echo $sum3
}

fchu () {
    sum4=$[$1/$2]
    echo $sum4
}
read -p "please input: " n j m 
    case $j in
    +)  
        fjia $n $m
        ;;  
    -)  
        fjian $n $m
        ;;  
    \*) 
        fcheng $n $m
        ;;  
    /)
        fchu $n $m
        ;;
    *)
        echo "error"
        exit 2
    esac

wKiom1e4FryTvcudAAApG8NHu8k338.png

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
fbnq () {
    if [ $1 -eq 0  ];then
        echo 0
    elif [ $1 -eq 1 ];then
        echo 1
    else
        echo "$[$(fbnq $[$1-1])+$(fbnq $[$1-2])]"
    fi  
}
read -p "please enter a number:" n
    fbnq $n

wKioL1e4F47xbaJsAAAT_xJ9Yoo215.png

6、漢諾塔(又稱河內塔)問題是源于印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

利用函數,實現N片盤的漢諾塔的移動步驟

#!/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

wKiom1e4GNKiCIhXAAAQHbIcaL0734.png

原創文章,作者:Groot,如若轉載,請注明出處:http://www.www58058.com/38766

(3)
GrootGroot
上一篇 2016-08-22
下一篇 2016-08-22

相關推薦

  • 自制一個小型Linux(附帶網絡功能)

      我們這次講述一下Linux啟動的啟動流程以及制作一個附帶網絡功能的mini linux 一、敘述 二、為什么要制作這么一個小型的系統 三、怎么制作 1、制作步驟 2、將虛擬機添加網絡功能 一、敘述   在制作一個小型的Linux之前,首先你得明白Linux系統的啟動過程,我們用一張圖來進行說明  二、為什…

    Linux干貨 2016-12-21
  • 一個簡單的負載均衡集群:web服務

    一個簡單的負載均衡集群:以web服務為例 實驗環境:三臺主機(CentOS 7.3)             主機1:IP地址 172.18.0.88(Haproxy代理服務器)             主機2:IP地址 172.…

    Linux干貨 2017-05-17
  • 文本處理工具基礎應用

                                                      &nbsp…

    Linux干貨 2016-08-07
  • xen虛擬化基礎篇

    Xen介紹:  xen是一個開放的源代碼虛擬機監視器,有劍橋大學研發。它打算在單個計算機上運行多達128個滿足特征的操作系統,操作系統必須進行顯示地修改("移植")以在Xen上運行(但是提供對用戶應用的兼容性)。這使得無需特殊硬件支持,就能達到高性能的虛擬化。 Xen由三部分組成:     第一部分…

    Linux干貨 2015-08-26
  • shell中的位置參數變量

    要了解位置變量,首先要知道什么是變量?  變量就是讓某一個特定的字符串來代表不固定的內容,簡單理解就是用一個簡單的“字眼”來替代另一個比較復雜或者容易變動的數據。 而什么又是位置變量呢?  位置變量就是bash將傳遞給腳本的參數,按照位置不同,保存在不同的位置變量中,以便于腳本調用這些變量。 位置參數變量: $1, $2, ……

    Linux干貨 2016-08-12
  • M20 – 1- 第三周博客:Linux中的權限以及特殊權限

    上一篇講到了用戶與用戶組,相信大家都明白了Linux中用戶與用戶組的含義和用處,那接下來講的就是Linux中設置用戶與用戶組有使用權限。 Linux用戶權限 何為權限,權限(privilege)是指某個特定的用戶具有特定的系統資源使用權力,而權限又有哪幾種呢。 Linux用戶中主要針對三類著三種權限:讀、寫、執行,而Linux中存在著目錄與文件,而目錄的權限…

    Linux干貨 2016-08-08

評論列表(1條)

  • 馬哥教育
    馬哥教育 2016-08-22 13:48

    select是一個很有用的模塊,他可以方便的實現與人交互,同時函數是linux哲學思想中重要的組成部分,模塊化的方式能快速的提高工作效率,本文總結的很詳細,再接再厲。

欧美性久久久久