shell腳本之選擇與執行

流程控制

過程式編程語言: 順序執行 選擇執行 循環執行

選擇執行:if語句 ?

注意:if語句可嵌套 ?

單分支

if 判斷條件:then

條件為真的分支代碼

fi ?

雙分支

if 判斷條件; then

條件為真的分支代碼

else

條件為假的分支代碼

fi

多分支

if CONDITION1; then

if-true

elif CONDITION2; then

if-ture

elif CONDITION3; then

if-ture

else all-false

fi ?

逐條件進行判斷,第一次遇為“真”條件時,執行其分支, 而后結束整個if語句

if實例

根據命令的退出狀態來執行命令

if ping -c1 -W2 station1 &> /dev/null; then

echo 'Station1 is UP' 

elif grep "station1" ~/maintenance.txt &> /dev/null

then

echo 'Station1 is undergoing maintenance‘

else

echo 'Station1 is unexpectedly DOWN!'

exit 1

fi

選擇執行:case語句

1.語法

case  $變量  in

PAT1) 分支1

;;

PAT2) 分支2

;;

*) 默認分支

;;

esac

2.case支持glob風格的通配符

*: 任意長度任意字符

?: 任意單個字符

[]:指定范圍內的任意單個字符

a|b: ab

練習

?1、寫一個腳本/root/bin/createuser.sh,實現如下功能: 使用一個用戶名做為參數,如果指定參數的用戶存在,就顯 示其存在,否則添加用戶;顯示添加的用戶的id號等信息

#!/bin/bash

useradd $1 &> /dev/null

if [ $? -eq 0 ]

then

echo 'user $1 added successful'

id $1

else

echo 'user exsit'

fi

                                              ?

2、寫一個腳本/root/bin/yesorno.sh,提示用戶輸入yes no,并判斷用戶輸入的是yes還是no,或是其它信息

#!/bin/bash

read -p "please input  yes or no! " a

case $a in

[Yy][Ee][Ss]|[Yy])

echo 'yes'

;;

[Nn][Oo]|[Nn])

echo 'no'

;;

*)

echo 'others'

esac?

3、寫一個腳本/root/bin/filetype.sh,判斷用戶輸入文件路 徑,顯示其文件類型(普通,目錄,鏈接,其它文件類型)

#!/bin/bash

read -p "please enter file:  " filename

if [ -L $filename ];then

   echo "$filename is Symbol file."

elif [ -c $filename ];then

   echo "$filename is char file."

elif [ -d $filename ];then

   echo "$filename is dir file."

elif [ -b $filename ];then

   echo "$filename is  block file."

elif [ -f $filename ];then

   echo "$filename is common file."

elif [ -P $filename ];then

   echo "$filename is pipe file."

elif [ -S $filename ];then

   echo "$filename is socket file."

else

  echo "please enter a Correct file"

fi?4、寫一個腳本/root/bin/checkint.sh,判斷用戶輸入的參數 是否為正整數

read -p 'please input numbers' n

[ -z "$n" ] && echo 'you must input numbers' && exit

[ "$n" -eq 0 ] &> /dev/null && echo "$n is " && exit

if let var=$n &> /dev/null;then

  if [ "$?" -eq 0 ];then

     if [ "$n" -lt 0 ];then

           echo "$n is 負整數"

     else

           echo "$n is 正整數"

     fi

  fi

else

echo "$n 不是一個整數"

fi

循環執行

將某代碼段重復運行多次

重復運行多少次: 循環次數事先已知 ,循環次數事先未知 。

進入條件:條件滿足時才進入循環

退出條件:每個循環都應該有退出條件

for, while, until

for循環 ?

兩種方式:(1)遍歷列表

for 變量名 in 列表;do

循環體

done ?

進入條件:只要列表有元素,即可進入循環

退出條件:列表中的元素遍歷完成

          2)控制變量

執行機制:依次將列表中的元素賦值給“變量名”每次賦值后即執 行一次循環體直到列表中的元素耗盡,循環結束。

列表生成方式:(1) 直接給出列表

(2) 整數列表 (a) {start..end}

(b) $(seq [start [step]] end)

                                             

(3) 返回列表的命令 $(COMMAND)

(4) 使用glob,如:*.sh

(5) 變量引用; $@, $*

練習:for實現 ?

  1. 1.     判斷/var/目錄下所有文件的類型

for filename in /var/log/*;do

if [ -L $filename ];then

   echo "$filename is Symbol file."

elif [ -c $filename ];then

   echo "$filename is char file."

elif [ -d $filename ];then

   echo "$filename is dir file."

elif [ -b $filename ];then

   echo "$filename is  block file."

elif [ -f $filename ];then

   echo "$filename is common file."

elif [ -P $filename ];then

   echo "$filename is pipe file."

elif [ -S $filename ];then

   echo "$filename is socket file."

else

  echo "please enter a Correct file"

fi

done?

2.添加10個用戶user1-user10,密碼同用戶名

if [[ $# -lt 1 ]]

then

    echo -e "Error: No option \n\t-d\tdelete user1-user10\n\t-a\tadd user1-user10 "

    exit 1

fi

for i in $(seq 10);do

    case $1 in

        -d|–del)

            if id user$i &> /dev/null;then

                userdel -r user$i

                echo "user$i: Delete complete!"

            else

                echo "user$i: No such user!"

            fi

            ;;

        -a|–add)

            if id user$i &> /dev/null;then

                echo "user$i"| passwd –stdin "user$i" &> /dev/null

                echo -e  "user$i: Already existed!\nAnd authentication tokens updated successful!"

            else

                useradd user$i &> /dev/null

                echo "user$i"| passwd –stdin "user$i" &> /dev/null

                echo " user$i: Add complete!"

            fi

            ;;

        *)?

3./etc/rc.d/rc3.d目錄下分別有多個以K開頭和以S開頭的 文件;分別讀取每個文件,以K開頭的文件輸出為文件加stop ,以S開頭的文件輸出為文件名加start

“K34filename stop”

  “S66filename start”

for i in `ls /etc/rc.d/rc3.d`

do

    FileC1=`echo $i | cut -c1`

    case $FileC1 in

        K)

            echo -e "$i\tstop"

            ;;

        S)

            echo -e "$i\tstart"

            ;;

        *)

            echo "unkown file"

            ;;

    esac

done

4.寫一個腳本,提示輸入正整數n的值,計算1+2+3+…n 總和

#!/bin/bash

read -p 'please input the number' n

num=`echo $n|grep "^[[:digit:]]\+$"`

if echo $n|grep -q  "^[[:digit:]]\+$" ;then

        if [ $num -eq 0 ];then

                echo "the number is 0"

                exit

        fi

else

        echo "the number is negtive"

        exit

fi

string=0

for i in `seq $n`;do

        sum=$[$sum+$i]

        string=$string+$i

done

echo "$string=$sum"

5.寫一個腳本,提示請輸入網絡地址,如192.168.0.0,判 斷輸入的網段中主機在線狀態 ?

echo -n "Enter IP:"
read IP
#get IP segment
Segment=`echo $IP | cut -d. -f1-3 `.
#
if echo $IP | egrep '\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>' &>/dev/null
then
    #test only  5 host
    for i in `seq 240 255`
    do
        if ping -c 1 -W 1 $Segment$i &> /dev/null
        then
            echo -e "$Segment$i\tonline"
        else
            echo -e "$Segment$i\toffline"
        fi
    done
else
    echo "$IP is invalid"
fi

6.打印九九乘法表

#!/bin/bash

for j in {1..9};do

      for i in $(seq 1 $j);do

           echo -n -e "${i}X${j}=$[${i}*${j}]\t"

      done

      echo

done

while循環 ?

while CONDITION; do  

循環體

done ?

進入條件:CONDITION測試為真

退出條件:CONDITION測試為假

CONDITION:循環控制條件;進入循環之前,先做一次判 斷;每一次循環之后會再次做判斷;條件為“true”,則執行 一次循環;直到條件測試狀態為“false”終止循環,因此:CONDTION一般應該有循環控制變量;而此變量的值 會在循環體不斷地被修正 .?

進入條件:CONDITIONtrue; ?

退出條件:CONDITIONfalse

練習:用while實現 ?

1.100以內所有正整數之和 ?

shell腳本之選擇與執行

2.通過ping命令探測172.16.250.1-254范圍內的所有主機 的在線狀態,統計在線主機和離線主機各多少。

shell腳本之選擇與執行

3.打印九九乘法表

shell腳本之選擇與執行?

4.利用變量RANDOM生成10個隨機數字,輸出這個10數字 ,并顯示其中的最大者和最小者

shell腳本之選擇與執行

5.打印國際象棋棋盤

shell腳本之選擇與執行

until循環 ?

until CONDITION; do

循環體 ?

Done

進入條件:CONDITION測試為假

退出條件:CONDITION測試為真

練習:用until實現

  1. 1.     每隔3秒鐘到系統上獲取已經登錄的用戶的信息;如果發 現用戶hacker登錄,則將登錄時間和主機記錄于日志 /var/log/login.log,并提示該用戶退出系統。

#!/bin/bash

while true ;do

      if who | grep "^hacker\>" &> /dev/null;then

                   break

      fi

      sleep 3

done

echo "$(date +"%F %T") hacker logged on" >> /tmp/users.log

#!/bin/bash

      until who | grep "^hacker\>" &> /dev/null;do

         sleep 3

done

echo "$(date +"%F %T) hacker logged on" >> /tmp/users.log

2.隨機生成10以內的數字,實現猜字游戲,提示比較大或小 ,相等則退出。

shell腳本之選擇與執行

break循環控制語句

用于循環體中 ?

break [N]:提前結束第N層循環,最內層為第1

while CONDTIITON1; do

CMD1

if CONDITION2; then

break

fi

CMDn

Done

整個until循環結束

exit是退出整個腳本

  退出內循環,執行外循環

死循環創建

while true; do

循環體 ?

Done

退出方式:某個測試條件滿足時,讓循環體制性break命令

 

until false; do

循環體 ?

Done

for特殊用法

1.while循環的特殊用法(遍歷文件的每一行):

while read line; do

循環體

done < /PATH/FROM/SOMEFILE ?

依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將 行賦值給變量line

練習

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

shell腳本之選擇與執行

2.雙小括號方法

((…))格式,也可以用于算術運算 ?

雙小括號方法也可以使bash Shell實現C語言風格的變量操作

#I=10

#((I++))

for循環的特殊格式:

for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))

do

循環體

done ?

 

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

控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算 ,而后再做條件判斷。

select 循環與菜單 ?

select variable in list

do

循環體命令

done ?

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

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

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

Selectcase

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

select 經常和 case 聯合使用 ?

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

函數介紹

函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程。把一段獨立功能的代碼當做一個整體,并為之一個名字;命名的代碼段,此即為函數。

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

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

Shell程序在子Shell中運行 ?

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

定義函數

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

語法一: function  f_name {

函數體

} ?

語法二: function f_name  ()  {

 …函數體

 } ?

語法三: f_name  ()   {

函數體

}

如圖,函數中不能直接使用$1等數字參數,所以用過度的中間參數。

函數使用

函數的定義和使用: 可在交互式環境下定義函數 (測試環境下使用)

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

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

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

調用:給定函數名

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

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

函數返回值

函數有兩種返回值: ?

1.函數的執行結果返回值: (1) 使用echoprintf命令進行輸出

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

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

(2) 自定義退出狀態碼,其格式為: return  從函數中返回,用最后狀態命令決定返回值;

 return 0  無錯誤返回。

return 1-255  有錯誤返回.

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

示例: $dir() {

          > ls –l

          > }

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

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

在腳本中定義及使用函數

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

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

示例: $cat func1

#!/bin/bash

# func1

hello() {

echo "Hello there today's date is `date +%F`"

}

echo "now going to the function hello"

hello

echo "back from the function"  

使用函數文件

可以將經常使用的函數存入函數文件,然后將函 數文件載入shell。 文件名可任意選取,但最好與相關任務有某種聯 系。例如:functions.main ?

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

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

創建函數文件

函數文件示例:

$cat  functions.main

#!/bin/bash

#functions.main

findit()

{

if [ $# -lt 1 ] ;  then

echo "Usage:findit file"

return 1

fi

find / -name $1 –print

}

載入函數

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

定位函數文件并載入shell的格式: . filename  source   filename  注意:此即<> <空格> <文件名這里的文件名要帶正確路徑 ?

示例:上例中的函數,可使用如下命令: $ . functions.main

檢查載入函數

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

示例:

$set

findit=( ) {

if [ $# -lt 1 ]; then

echo "usage :findit file";

return 1

fi

find / -name $1 -print

}

執行shell函數

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

示例: $findit groups

/usr/bin/groups

/usr/local/backups/groups.bak

刪除shell函數

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

命令格式為: ?unset  function_name

實例: $unset findit 再鍵入set命令,函數將不再顯示

函數參數

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

示例1:添加10個用戶

     添加用戶的功能使用函數實現,用戶名作為參數傳遞給函數

#!/bin/bash

#2:user exist

#函數定義

addusers() {

        #判斷用戶是否存在

        if id $1 &> /dev/null; then

        #存在就返回一個2

                return 2

        else

                #不存在就添加用戶

                useradd $1

                #用戶是否添加成功

                retuval=$?

                #返回添加成功的值

                return $retuval

        fi

}

#引用函數

for i in {1..10};do

        addusers ${1}${i}

        #位置參數不能直接被引用

        retuval=$?

        #調用addusers的參數,如果$?=0則表示用戶添加成功

        if [ $retuval -eq 0 ];then

                #${1}是用戶名,${i}是用戶后面跟著的數字如user1,user是給定的用戶名

                echo "add user ${1}${i} finished"

        elif [ $retuval -eq 2 ];then

                echo "user ${1}${i} exists"

        else

                echo "unknow error"

        fi

done

函數變量

?變量作用域:

環境變量:當前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)!

?   示例: fact.sh

#!/bin/bash

#

fact() {

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

echo 1

else

echo $[$1*$(fact $[$1-1])]

fi

}

fact $1 

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

(1)
JaggerJagger
上一篇 2016-09-19
下一篇 2016-09-19

相關推薦

  • Linux第八周小結

    1、寫一個腳本,使用ping命令探測172.16.250.1-172.16.250.254之間的所有主機的在線狀態 在線的主機使用綠色顯示 不在線的主使用紅色顯示 #!/bin/bash # for i in {1..254};do if ping -c 6 -w 1 192.168.1.$i &> /dev/null;then echo -e…

    Linux干貨 2017-08-20
  • 一個簡單小例子來說一下Rescue營救模式

    昨天不小心將/lib64下的一個動態庫文件libc.so.6(很多命令都依賴的)給移動到了/root下,然后除了一些內部命令可用外,其余命令都不能用了,然后就想著看看重啟可不可以修復,結果重啟后就再也開不了機了,心想著這可咋整,要不用最快的方式進行快照恢復吧,結果老師就說了,不能使用快照,讓我們使用Rescue營救模式進行恢復,然后在恢復的過程中就發現一個問…

    Linux干貨 2017-08-21
  • sed

    Stream EDitor, 行編輯器 sed是一種流編輯器,它一次處理一行內容。處理時,把當前 處理的行存儲在臨時緩沖區中,稱為“模式空間”(pattern space),接著用sed命令處理緩沖區中的內容,處理完成后 ,把緩沖區的內容送往屏幕。然后讀入下行,執行下一個循環 。如果沒有使諸如‘D’的特殊命令,那會在兩個循環之間清空 模式空間,但不會清空保留…

    Linux干貨 2017-12-03
  • shell腳本編程和位置變量

    編程基礎 程序:指令+數據    程序編程風格:       過程式:以指令為中心,數據服務于指令       對象式:以數據為中心,指令服務于數據    shell:提供了編程能…

    Linux干貨 2016-08-16
  • N23-卡卡琦-第一周

    1、描述計算機的組成及其功能 硬件: 控制器:是整個計算機的中樞神經,其功能是對程序規定的控制信息進行解釋,根據其要求進行控制,調度程序、數據、地址,協調計算機各部分工作及內存與外設的訪問等;運算器:運算器的功能是對數據進行各種算術運算和邏輯運算,即對數據進行加工處理;存儲器:存儲器的功能是存儲程序、數據和各種信號、命令等信息,并在需要時提供這些信息;輸入輸…

    Linux干貨 2016-11-16
  • DHCP服務

    dhcp server: DHCP:Dynamic Host Configuration Protocol     arp –> address resolving Protocol     &nbsp…

    Linux干貨 2016-11-01

評論列表(1條)

  • lyx
    lyx 2016-11-20 21:05

    路過,腳本習題很好,點個贊!

欧美性久久久久