bash腳本編程基礎

bash腳本編程:


首先了解一下shell腳本編程的特點:

過程式編程語言

腳本類語言

解釋型語言


過程式編程語言:

順序執行結構:

以從左到右,從上到下順序執行所有的語句(命令)

shell腳本的主體結構;

選擇執行結構:

依照給定條件的邏輯判斷結果或者依照可選的取值範圍,進而選擇某個分支中的語句                 來執行;

if:分支選擇標準:邏輯判斷的結果;

case:分支選擇標準:根據可選的取值;

循環執行結構:

對於某特定語句,重複執行0次,1次或多次;

for:遍歷指定的列表;

while:根據邏輯判斷的結果;

until:根據邏輯判斷的結果;

select:死循環,利用循環機制提供選擇列表;

1.

選擇執行結構:

if語句:

if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi

if語句單分支結構:如果條件爲真,則執行then後的命令,否則,不做任何操作;

if CONDITION

then STATEMENT

fi


if CONDITION ; then

STATEMENT1

STATEMENT2

...

fi

  注意:想要執行then後面的STATEMENTS,前提條件是CONDITION部分爲真;


if語句的雙分支結構:如果條件爲真,就執行then後面的命令;否則就執行else後面的命令;

if CONDITION ; then

STATEMENT

...

else

STATEMENT

...

fi


if語句的多分支結構:首先判斷CONDITION1是否爲真,如果爲真,則執行第一個then後面的語句;否則就判斷CONDITION2是否爲真,如果爲真,就執行第二個then後面的語句;否則就判斷CONDITION3是否爲真,如果爲真,就執行第三個then後面的語句...;如果所有的CONDITION都爲假,就執行else後面的語句;

if CONDITION1 ; then

STATEMENT

...

elif CONDITION2 ; then

STATEMENT

...

elif CONDITION3 ; then

 STATEMENT

 ...

...

else

STATEMENT

...

fi


建議:if多分支結構,能不用就不用;


bash腳本編程之用戶交互:

位置參數變量:$1, $2, $3, ...

特殊變量:

$#:所有的位置參數的總數;

$*:給出的所有位置參數的列表;當使用雙引號引用時,整個參數列表被當做一個字                     符串;

$@:給出的所有位置參數的列表;當時有雙引號引用時,每個參數作爲單獨的字符串                     存在;

$0:所執行的腳本文件自身的路徑;


read命令:

read [-a 數組] [-p 提示符] [-t 超時] [名稱 ...]

名稱一般爲變量名或數組名:如果不寫名稱,則系統會將read讀到的信息保存在REPLY變量中;

注意:在使用read命令的時候,通常會使用-t選項來規定超時時間;一旦使用-t選項定義了超時時間,我們必須在後面判斷給定的變量是否爲空,如果爲空需要爲變量提供默認值;


2.

循環執行結構:

將一段代碼重複的執行0次、1次或多次;

一個好的循環結構,必須要包括兩個最重要的環節:

進入循環的條件:

開始循環時所滿足的條件;

退出循環的條件:

循環結束所滿足的條件;


bash腳本:for、while、until、select


for循環:

1.遍歷列表

for VAR_NAME in LIST ; do 循環體; done


for VAR_NAME in LIST ; do

循環體

done


VAR_NAME:任意指定的變量名稱,變量的值是從LIST中取值並賦值的;

循環體:一般來說是能夠用到VAR_NAME的命令或命令的組合;如果循環體中沒有包括                          VAR_NAME,則可能出現死循環;

LIST的生成方式:

1) 直接給出

2) 純整數列表

seq:輸出一個整數列表

seq [FIRST [INCREMENT]] LAST

3) 花括號展開

{FIRST..LAST}

4) 命令的執行結果的返回值

5) GLOBBING

6) 某些變量的引用:$@, $*


for循環:

進入循環的條件:LIST中有元素可以取用;

退出循環的條件:LIST中以被取空,再無元素可用;


for循環的特點:

1.幾乎不會出現死循環;

2.在執行循環的過程中,需要將這個LIST載入內存;因此對於大列表來說可能會過多                    的消耗內存和CPU資源;


注意:使用for循環嵌套的時候,外層for循環,控制行數的輸出;內層for循環,控制列數的輸出;


2.控制變量

for (( 表達式1; 表達式2; 表達式3 )); do 命令; done


for (( 表達式1; 表達式2; 表達式3 )) ; do

循環體

done

表達式1:爲變量賦初始值;

表達式2:循環的退出條件;

表達式3:變量值的變化規律;


例子:計算1-100之間的和

#!/bin/bash

for (( I=1; I<=100; I++ )); do

let SUM+=$I

done

echo $SUM


case分支選擇結構:

case 詞 in [模式 [| 模式]...) 命令 ;;]... esac

case 變量引用 in

模式1)

分支1

;;

模式2)

分支2

;;

...

*)

默認分支

;;

esac


模式(PATTERN):

1.普通的文本字符

2.globbing風格的通配符:

*:任意長度任意字符

?:任意的單個字符

[]:範圍內的任意單個字符

[^]:範圍外的任意單個字符

3.|:或


我們可以看出case與if是有很大的類似的。

if的多分支結構和case的分支結構之間的區別:

相同點:

1.都是條件爲真,執行對應分支的語句;條件爲假,就不執行;

2.都可以設置默認分支語句,即:所有條件都不匹配的時候,所執行的語句;

不同點:

1.if是根據命令的執行狀態返回值來判斷正確與否;case是根據變量的值的取值內容                    是否匹配模式來判斷正確與否;

2.case的每個分支都必須使用';;'結束;


while

while 命令; do 命令; done

while CONDITION ; do

循環體

done

進入循環條件:CONDITION一直爲真;

退出循環條件:CONDITION爲假;


until

until 命令; do 命令; done

until CONDITION ; do

循環體

done

進入循環條件:CONDITION一直爲假;

退出循環條件:CONDITION爲真;


while CONDITION ; do CMD ; done 

相當於 

until ! CONDITION ; do CMD ; done


注意:對於while和until兩個循環結構來講,如果要實施變量增量操作,必須手動給出;


給個例子對比一下他們之間的差別:

利用while和until循環結構,計算100以內所有整數的和;

#!/bin/bash

#

declare -i I=1

while [ $I -le 100 ] ; do

let SUM+=$I

let I++

done

echo $SUM


#!/bin/bash

#

declare -i I=1

until [ $I -gt 100 ] ; do

let SUM+=$I

let I++

done

echo $SUM



循環控制語句:continue、break

continue:

continue [n]

提前結束第n層的本次循環,直接進入下一輪條件判斷,若符合循環進入條件,則開啓下一輪循         環;

break:

break [n]

提前技術第n層循環;不再繼續後續循環;


無限循環用法:

while true ; do

循環體

done


until false ; do

循環體

done


友情提示:在此類的循環結構中,必須適當的使用continue和break,以保證循環不會一直持續下去;


能夠實現遍歷功能的while循環和until循環;

while read LINES ; do

循環體

done < /PATH/FROM/SOMEFILE


until ! read LINES ; do

循環體

done < /PATH/FROM/SOMEFILE


select

select循環主要用於創建一個菜單式列表,供用戶進行選擇;

列表是按照數字順序排列的,我們只要選擇數字即可;


一般來講,select與case一起使用;


select是一個無限循環結構,因此,必須在循環體中使用break命令以退出循環,或者可以使用exit命令直接終止腳本運行;


select NAME [in 詞語 ... ;] do 命令; done


select NAME [in LIST] ; do

命令

done


總結:

shell腳本編程語言:

過程式編程語言

順序:主體結構

選擇:

if

case

循環

for

遍歷列表:

控制變量

while

until

select


在學習腳本函數之前,我們先了解systemV風格的服務管理腳本。

systemV風格的服務管理腳本:

給腳本傳遞一些參數:start, stop, restart, status

myservice.sh

#!/bin/bash

#

lockfile="/var/lock/subsys/$(basename $0)"

case $1 in

start)

if [ -f $lockfile ] ; then

echo "服務已經啓動...."

else

touch $lockfile

echo "服務正在啓動...."

fi

;;

stop)

if [ -f $lockfile ] ; then

rm -f $lockfile

echo "服務已經停止...."

else

echo "服務尚未啓動..."

fi

;;

restart)

if [ -f $lockfile ] ; then

rm -f $lockfile

echo "服務已經停止...."

else

echo "服務尚未啓動..."

fi

if [ -f $lockfile ] ; then

echo "服務已經啓動...."

else

touch $lockfile

echo "服務正在啓動...."

fi

;;

status)

if [ -f $lockfile ] ; then

echo "服務已經啓動...."

else

echo "服務已經停止...."

fi

;;

*)

echo "Usage: $(basename $0) start|stop|restart|status"

exit 5

;;

esac


把那些在腳本中重複出現並且沒有任何改變的代碼,封裝起來,在適當的場景中調用執行;

程序員將這種被封裝起來的代碼稱爲功能體,或者叫模塊;

function —— 函數


在shell腳本編程中,函數是由若干條shell命令組成的語句塊;通常用於代碼重用和模塊化封裝;


函數裏面的內容和shell程序形式上是一致的;不同之處就是,shell代碼可以直接被執行;而函數中的內容,不能獨立執行,只有被調用的時候才執行;


函數是在shell程序的當前shell中運行的;

bash

bash script_file

function


定義函數:

函數是由兩部分組成:

函數名稱 + 函數體(能夠實現獨立功能的shell語句塊)


語法一:

function func_name {

函數體

}

語法二:

func_name() {

函數體

}

注意:函數名和()之間不能加空白字符;


注意:函數可以在交互式環境下定義,也可以在腳本中定義;


函數的使用

函數在定義的時候,其函數體中包含的所有命令均不會被執行;只有函數被調用的時候,纔會執行其中的命令語句;

調用方式:通過直接給出函數名稱的方式調用;


有很多的函數是存放於專門用於保存函數的文件中;如果想要調用這樣的文件中保存的函數,使用source命令(.)加載文件,然後再以直接給出函數名稱的方式調用函數;


使用set命令可以查看所有當前shell中生效的函數;

使用unset命令可以撤銷已經定義的函數;


函數的返回值:

兩種返回值:

函數的執行結果的返回值:

1.在函數體中使用了echo或printf命令輸出的結果;

2.在函數體中某些命令輸出的結果;

函數的狀態返回值:

1.函數中最後一條命令的執行狀態返回值;

2.自定義退出狀態碼:

return [n]

n:0-255 (1 2 127儘可能不使用)

0: 表示無錯誤返回

1-255:有錯誤返回


注意:只要函數在執行時,遇到了return命令,不管函數中的命令語句是否全部執行完成,立               刻退出函數;


函數的生命週期:

從被調用開始,到遇到return命令或全部的語句執行完成爲止;


函數的實參

    在函數體中,可以使用$1,$2,..位置變量爲函數提供參數;還可以使用$*或$@的方式引用所有位置參數;還可以使用$#計算爲函數傳遞的參數個數;


    在調用函數的時候,直接在函數名稱後面以空白字符分隔多個參數即可;比如:func_name arg1 arg2 ...


    傳遞給函數參數的位置參數,是調用函數的時候,函數名稱後面的以空白字符分隔的字符串序列;跟腳本的位置參數不是一回事;


變量:

shell中的變量爲弱變量

1.無需事先聲明

2.無需指定變量類型,默認爲字符型


變量分類:

環境變量(一般不會用):

當前shell及子shell

本地變量:

當前shell

局部變量:

local VAR_NAME=VALUE

當前函數體

位置變量

特殊變量


建議:手動撤銷自己定義或聲明的所有變量;


函數的遞歸調用

簡單來說,就是在函數體中調用函數自身;


例如求一個數的階乘:

#!/bin/bash

# Author: Tianyu.Zhao

#

fact(){

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

   echo 1

 else

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

 fi

}


echo -n "$1!="

fact $1


最後總結腳本編寫的步驟:

1.構建程序主體

默認是順序執行結構

根據需求添加相應的選擇結構和循環結構

2.確定完成某功能所需的命令

3.調試(bash -x /PATH/TO/SCRIPT_FILE)

4.寫明幫助信息


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章