shell腳本4——特殊循環和函數

循環的特殊用法:

1、while循環的特殊用法之遍歷文件的每一行

while read line; do
    循環體
done < /PATH/FROM/SOMEFILE

依次讀取/PATH/FROM/SOMEFILE文件中的每一行,將每一行賦值給變量line,從而實現對文件的增刪改

練習:掃描/etc/passwd 文件每一行,如發現GECOS 字段為空,則填充用戶名和單位電話為62985600 ,并提示該用戶的GECOS信息修改成功。

#!/bin/bash
#description if user no gecos add something to gecos
#version 0.1
#author gaomeng
#date 20160819
#
while read line ; do
    gecos=`echo $line | cut -d: -f5`
    if [ -z $gecos ] &> /dev/null ; then
        username=`echo $line | cut -d: -f1`
        usermod -c "$username 62985600" $username
        echo "$username gecos is changed."
    fi
done < /etc/passwd
[root@CentOS6 bin]# getent passwd gao
gao:x:500:500::/home/gao:/bin/bash  //gecos段無信息
[root@CentOS6 bin]# addgecos.sh
abrt gecos is changed.
ntp gecos is changed.
postfix gecos is changed.
gdm gecos is changed.
tcpdump gecos is changed.
hlr gecos is changed.
gao gecos is changed.
hadoop gecos is changed.
test gecos is changed.
[root@CentOS6 bin]# getent passwd gao
gao:x:500:500:gao 62985600:/home/gao:/bin/bash  //gecos段有信息

2、C語言風格的for循環:

雙小括號方法,即((…))格式,代替shell中的in LIST 菜單

單純用(( ))也可重定義變量值,比如 a=5; ((a++))可將$a重定義為6

for 循環的C語言風格:

for ((控制變量的初始化; 退出此for循環的條件; 控制變量的修正表達式))
do
    循環體
done

控制變量初始化:僅在運行到循環代碼段時執行一次

控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而后再做退出for循環的條件判斷,若滿足條件則退出循環,若不滿足則繼續循環

例如:打印99乘法表

#!/bin/bash
#description echo 9 * 9
#version 0.1
#author gaomeng
#date 20160819
#
for (( i=1 ; i<=9 ; i++ ))
do
    for (( j=1 ; j<=i ; j++ ))
    do
        echo -en "$j*$i=$[$i*$j]\t"
    done
    echo
done
[root@CentOS6 bin]# bash for99.sh
1*1=1
1*2=2    2*2=4
1*3=3    2*3=6     3*3=9
1*4=4    2*4=8     3*4=12    4*4=16
1*5=5    2*5=10    3*5=15    4*5=20    5*5=25
1*6=6    2*6=12    3*6=18    4*6=24    5*6=30    6*6=36
1*7=7    2*7=14    3*7=21    4*7=28    5*7=35    6*7=42    7*7=49
1*8=8    2*8=16    3*8=24    4*8=32    5*8=40    6*8=48    7*8=56    8*8=64
1*9=9    2*9=18    3*9=27    4*9=36    5*9=45    6*9=54    7*9=63    8*9=72    9*9=81

3、select循環與菜單

select variable in list
do
    循環體命令
done

a.select循環主要用于創建菜單,按數字順序排列的示菜單項將顯示在標準錯誤上,并顯示PS3提示符,等待用戶輸入,用戶也可在腳本中修改PS3提示符,使之更加人性化

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

c.用戶輸入被保存在內置變量REPLY中,可以在語句中打印此變量

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

e.select經常和case聯合使用

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

例如:1.沒有修改PS3提示符,也沒有配合case語句使用

#!/bin/bash
#description show select
#version 0.1
#authre gaomeng
#date 20160819
#
select list in gongbaojiding hongshaorou huobaofeichang shaopaigu
do
    echo $list
done
[root@CentOS6 bin]# select.sh
1) gongbaojiding
2) hongshaorou
3) huobaofeichang
4) shaopaigu
#? 1
gongbaojiding
#? 2
hongshaorou
#? 3
huobaofeichang
#? 4
shaopaigu
#? 5
#? 6
#? ^C

2.修改了PS3,配合使用了case語句:

#!/bin/bash
#description show select
#version 0.3
#authre gaomeng
#date 20160819
#
PS3="What do you want:"
select list in gongbaojiding hongshaorou huobaofeichang shaopaigu
do
    case $list in
    gongbaojiding)
        echo "$list is 20¥"
        exit;;
    hongshaorou)
        echo "$list is 30¥"
        exit;;
    huobaofeichang)
        echo "$list is 25¥"
        exit;;
    shaopaigu)
        echo "$list is 40¥"
        exit;;
    *)
        echo "no the list, please choice other."
    esac
done
[root@CentOS6 bin]# select.sh
1) gongbaojiding
2) hongshaorou
3) huobaofeichang
4) shaopaigu
What do you want:1
gongbaojiding is 20¥
[root@CentOS6 bin]# select.sh
1) gongbaojiding
2) hongshaorou
3) huobaofeichang
4) shaopaigu
What do you want:4
shaopaigu is 40¥
[root@CentOS6 bin]# select.sh
1) gongbaojiding
2) hongshaorou
3) huobaofeichang
4) shaopaigu
What do you want:8
no the list, please choice other.
What do you want:3
huobaofeichang is 25¥

函數:

函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程,即有個功能或模塊,我們在代碼中會反復使用,則可以寫成函數,使用是調用函數即可,而不用多次編寫代碼

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

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

     Shell程序在子Shell中運行

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

函數的定義:

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

定義:

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

     語法一:

     function f_name {

     … 函數體…

     }

     語法二:

     function f_name () {

     … 函數體…

     }

     語法三:

     f_name() {

     … 函數體…

     }

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

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

c.可放在只包含函數的單獨文件中,在腳本中用source 和. 調用函數

d.可以將經常使用的函數存入函數文件,然后將函數文件載入shell

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

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

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

載入函數:

shell腳本中調用一個已創建好函數文件:

. filename 或 source filename

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

這里的文件名要使用路徑,絕對路徑或者相對路徑都可以

調用函數:

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

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

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

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

刪除函數:

使用unset命令完成此功能.

unset function_name

函數的返回值:

函數的執行結果返回值:

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

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

函數的退出狀態碼:

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

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

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

         return 0 無錯誤返回。

         return 1-255 有錯誤

函數參數:

函數可以接受參數:

傳遞參數給函數:調用函數時,在函數名后面以空白分隔給定參數列表即可;例如“testfunc arg1 arg2 …”

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

注意:請區分函數中的$1和腳本的$1不同之處

例如:如下腳本

#!/bin/bash
#description test function $1 $2
#version 0.1
#author gaomeng
#date 20160819
#
prin() {
    echo "prin function \$1 is $1."
    echo "prin function \$2 is $2."
}

echo "\$1 is $1."
echo "\$2 is $2."
prin $2 $1
[root@CentOS6 bin]# functiontest.sh 3 9
$1 is 3.
$2 is 9.
prin function $1 is 9.
prin function $2 is 3.

函數變量:

變量作用域:

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

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

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

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

         在函數中定義局部變量的方法

             local NAME=VALUE

#!/bin/bash
#description
#version 0.1
#author gaomeng
#date 20160819
#
test1() {
    echo "test1 name=$name"   //沒有定義變量
}
test2() {
    local name=haha   //定義了局部變量
    echo "test2 name=$name"
}
test3() {
    name=haha    //直接定義了一個變量,會影響腳本中的變量值?
    echo "test3 name=$name"
}
name=gaomeng
echo "name=$name"
test1
echo "name=$name"
test2
echo "name=$name"
test3
echo "name=$name"

[root@CentOS6 bin]# bash functiontest1.sh
name=gaomeng
test1 name=gaomeng        //函數中沒有定義變量,則自動使用腳本中的同名變量
name=gaomeng
test2 name=haha
name=gaomeng            //在函數中定義的局部變量沒有影響腳本中的變量
test3 name=haha         
name=haha            //在函數中定義的變量影響了腳本中的變量

函數遞歸:

函數直接或間接調用自身

注意遞歸層數

遞歸實例:

階乘是基斯頓·于 卡曼于 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)!


例:fact.sh

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

練習:1、寫一個函數實現兩個數字做為參數,返回最大值

#!/bin/bash
#description input two number, and retuen max number.
#version 0.1
#author gaomeng
#date 20160818
#
max(){
    if [ $1 -gt $2 ]; then
        echo "max number is: $1"
    else
        echo "max number is: $2"
    fi
}

read -p "Input first number: " num1
until echo $num1 | grep -qE "^[0-9]+$";do
    read -p "your number error, Input first number: " num1
done
read -p "Input second number: " num2
until echo $num2 | grep -qE "^[0-9]+$";do
    read -p "your number error, Input second number: " num2
done

max $num1 $num2

[root@CentOS6 bin]# function3.sh
Input first number: sdf
your number error, Input first number: 123
Input second number: -124
your number error, Input second number: sdkf
your number error, Input second number: 100
max number is: 123

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

#!/bin/bash
#desription four arithmetic operation
#version 0.1
#author gaomeng
#date 20160818
#
operation() {
    if [ $2 == "+" ]; then
        echo "$1+$3=$[$1+$3]"
    elif [ $2 == "-" ]; then
        echo "$1-$3=$[$1-$3]"
    elif [ $2 == "x" ]; then
        echo "${1}x${3}=$[$1*$3]"
    elif [ $2 == "/" ]; then
        echo "$1/$3=$[$1/$3]"
    else
        echo "this is error symbol."
    fi
}

read -p "Input first number: " num1
until echo $num1 | grep -qE "^\-?[0-9]+$";do
    read -p "your number error, Input first number: " num1
done

i=0
until [ $i -eq 1 ];do
    read -p "Input operation symbol( please x instead of * ): " num2
    [ $num2 == "+" -o $num2 == "-" -o $num2 == "x" -o $num2 == "/" ] &> /dev/null &&i=1
done

read -p "Input second number: " num3
until echo $num3 | grep -qE "^\-?[0-9]+$";do
    read -p "your number error, Input second number: " num3
done

operation $num1 $num2 $num3
[root@CentOS6 bin]# function4.sh
Input first number: sdf
your number error, Input first number: 5
Input operation symbol( please x instead of * ): *
Input operation symbol( please x instead of * ): x
Input second number: -4
5x-4=-20

3、斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列: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 階斐波那契數列

0  1   2   3   4   5   6   7    8    9

0、1 、1 、2 、3 、5 、8 、13 、21 、34

#!/bin/bash
#description series of rabbit
#version 0.3
#author gaomeng
#date 20160818
#
series() {
    if [ $1 -eq 0 ]; then
        sum=0
    elif [ $1 -eq 1 ];then
        sum=1
    else
        let sum=`series $[$1-1]`+`series $[$1-2]`
    fi
    echo "$sum"
}

read -p "Please input month number: " num
until echo $num | grep -qE "^[0-9]+$";do
    read -p "your number error, Input month number: " num
done

series $num
[root@CentOS6 bin]# function5.sh
Please input month number: -123
your number error, Input month number: sdf
your number error, Input month number: 8
21
[root@CentOS6 bin]# function5.sh
Please input month number: 1.02323
your number error, Input month number: 10
55

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

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

#!/bin/bash
#description hanoi game
#version 0.2
#author gaomeng
#date 20160818
#
i=1
move() {
    echo -e "$i)\t$1 plate from $2 to $3."
    let i++
}
hanoi() {
    if [ $1 -eq 1 ]; then
        move $1 $2 $4
    else
        hanoi $[$1-1] $2 $4 $3
        move $1 $2 $4
        hanoi $[$1-1] $3 $2 $4
    fi
}

read -p "Please input move plate numbers: " num
until echo $num | grep -qE "^[0-9]+$";do
    read -p "your number error, Input move plate number: " num
done

hanoi $num A B C
[root@CentOS6 bin]# function6.sh
Please input move plate numbers: 3
1)1 plate from A to C.
2)2 plate from A to B.
3)1 plate from C to B.
4)3 plate from A to C.
5)1 plate from B to A.
6)2 plate from B to C.
7)1 plate from A to C.
[root@CentOS6 bin]# function6.sh
Please input move plate numbers: 4
1)1 plate from A to B.
2)2 plate from A to C.
3)1 plate from B to C.
4)3 plate from A to B.
5)1 plate from C to A.
6)2 plate from C to B.
7)1 plate from A to B.
8)4 plate from A to C.
9)1 plate from B to C.
10)2 plate from B to A.
11)1 plate from C to A.
12)3 plate from B to C.
13)1 plate from A to B.
14)2 plate from A to C.
15)1 plate from B to C.

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

(0)
megedugaomegedugao
上一篇 2016-08-21
下一篇 2016-08-22

相關推薦

  • 馬哥教育網絡班21期-第二周課程練習

    第二周課程練習 1、Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示?     1.1 目錄管理類命令:cd,pwd,ls,mkdir,rmdir,tree          1.1.1 cd:主要功能是改變當前目錄,…

    Linux干貨 2016-07-04
  • 第五周作業

    1、顯示當前系統上root,fedora或user1用戶的默認shell。 [root@hostname ~]# grep -E ‘^(root|fedora|user1)’ /etc/passwd | cut -d: -f1,7 root:/bin/bash 2、找出/etc/rc.d/init.d/functions文件中某詞后面跟一組小括號的行,形如:…

    Linux干貨 2017-08-04
  • 馬哥教育21期網絡班—第11周課程+練習—-成長進行時–不退步–上

    1、詳細描述一次加密通訊的過程,結合圖示最佳。 對稱加密: 加密和解密使用同一個密鑰; 缺點:如何通信方多的話,需要保存多組密鑰 公鑰加密:密鑰是成對兒出現 公鑰:公開給所有人;pubkey 私鑰:自己留存,必須保證其私密性;secret key 特點:用公鑰加密的數據,只能使用與之配對兒的私鑰解密;反之亦然; 數字簽名:主要在于讓接收方確認發送方…

    Linux干貨 2016-09-19
  • linux哲學思想

    有關運維,在哲學上的思想。 正確的哲學思想在我看來就是公理,就是像1+1=2一樣大家都必須得遵守的公理。 當然,所有的公理都是有前提的,而有關linux的哲學思想當然是在linux環境這個大前提下。才是公理。在我看來,公理就是在學習知識之前所要依靠的準則,linux下的一切都在這些準則下。 比如: 一切接文件  linux下所有都是以文件的形式保存…

    2017-07-22
  • 磁盤分區,文件系統的創建、修改和檢測

        寫博客,對我來說不僅是學習的過程,也是一個心理歷練的過程,多說無益,開始吧?。?!     博客是馬哥視頻里的博客作業:文件系統的創建、修改和檢測。我就從磁盤管理開始把      環境:     創建的centos6.5虛擬機 &nb…

    Linux干貨 2016-06-26
  • Linux系統終端類型

    引言 終端(Terminal)也稱終端設備,是計算機網絡中處于網絡最外圍的設備,主要用于用戶信息的輸入以及處理結果的輸出等。在早期計算機系統中,由于計算機主機昂貴,因此一個主機一般會配置多個終端,這些終端本身不具備計算能力,僅僅承擔信息輸入輸出的工作,運算和處理均由主機來完成,在個人計算機時代,個人計算機可以運行稱為終端仿真器的程序來模仿一個終端的工作。 &…

    Linux干貨 2016-10-19
欧美性久久久久