Shell腳本編程—特殊用法及函數
一、while的特殊用法:
1、使用格式:
while read 變量名;do
循環體
done </PATH/TO/filename
注:依次從指定的文件中的內容逐行讀取,并把讀取到的每行賦值給變量。
2、例題:
掃描/etc/passwd文件每一行,如發現GECOS字段為空,則填充用戶名和單位電話為13800138000,并提示該用戶的GECOS信息修改成功。
如下圖,修改前:
如下圖,修改后及代碼:(如果不需要操作過程的信息,可在代碼行“chfn后面添加/dev/null”)
腳本代碼:
二、雙小括號的使用(類似C語言的編寫風格):
1、雙小括號方法,可以使bash Shell實現C語言風格的變量操作;也可以用于算術運算,即((…))格式,
#I=10
#((I++))
for循環的特殊格式:
for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式));do
循環體
done
控制變量初始化:僅在運行到循環代碼段時執行一次
控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而后再做條件判斷
2、例題:做九九乘法
腳本代碼:
代碼及效果圖:
三、select菜單的特殊使用:
1、使用格式:
selec t variable in list ;do
循環體命令
done
2、select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示PS3 提示符,等待用戶輸入;用戶輸入菜單列表中的某個數字,執行相應的命令;用戶輸入被保存在內置變量REPLY 中。
3、select與case的結合使用:
select 是個無限循環,因此要記住用break 命令退出循環,或用exit 命令終止腳本。也可以按ctrl+c 退出循環。
select 經常和case 聯合使用
與for 循環類似,可以省略in list ,此時使用位置參量($*,$@……)
4、例題:做一個腳本文件初始創建的模板
如下,為腳本代碼、執行步驟及效果圖:
四、函數:
1、函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程。
2、函數與shell的對比:
它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分。
3、函數和shell程序比較相似,區別在于:
Shell程序在子Shell中運行
而Shell函數在當前Shell中運行。因此在當前Shell中,函數可以對shell中變量進行修改
4、認識函數的使用格式:函數由兩部分組成:函數名和函數體。
語法一:
function f_name{
…函數體…
}
語法二:
function f_name(){
…函數體…
}
語法三:
f_name(){
…函數體…
}
5、函數的定義和使用:
可在交互式環境下定義函數
可將函數放在腳本文件中作為它的一部分
可放在只包含函數的單獨文件中
調用:函數只有被調用才會執行;
調用:給定函數名
函數名出現的地方,會被自動替換為函數代碼
函數的生命周期:被調用時創建,返回時終止
6、簡單認識函數:如下圖
定義該函數add后,若在#后面鍵入add,其顯示結果同ls-l的作用相同。刪除定義的函數命令是:#unset add
注意:腳本內的$1;$2變量與函數add內的$1;$2是不一樣的,要區分開來。
7、腳本內的函數調用:
函數在使用前必須定義,因此應將函數定義放在腳本開始部分,直至shell首次發現它后才能使用
調用函數僅使用其函數名即可。
如下圖:
注意,下圖中的變量不能夠放在函數的前面,否則函數無法使用和調用賦值計算:
8、寫一個專門存放函數的文本,提供給其他的程序調用:
A、可以將經常使用的函數存入函數文件,然后將函數文件載入shell;件名可任意選取,但最好與相關任務有某種聯系。例如:functions.main
B、一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂?/span>set命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數。
C、若要改動函數,首先用unset命令從shell中刪除函數。改動完畢后,再重新載入此文件。
D、調用函數文本格式:函數文件已創建好后,要將它載入shell
定位函數文件并載入shell的格式:
. filename 或source filename
注意:此即<點> <空格> <文件名> ;這里的文件名要帶正確路徑
事例:
方法一:
方法二:
方法三:shell進程里面的子shell調用同一個函數:
(注:函數可以接受參數,調用函數時,在函數名后面以空白分隔給定參數列表即可;例如“testfuncarg1 arg2 …”;在函數體中當中,可使用$1, $2, …調用這些參數;還可以使用$@, $*, $#等特殊變量)
9、函數的變量:
A、變量作用域:
環境變量:當前shell和子shell有效
本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范圍是當前shell腳本程序文件,包括腳本中的函數。
局部變量:函數的生命周期;函數結束時變量被自動銷毀
注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量。
B、在函數中定義局部變量的方法:local NAME=VALUE
事例:局部變量的定義
變量定義前:如下圖,shell腳本里面的變量與函數里面的變量名同名的情況下,shell腳本的變量無效。
變量定義后:
10、函數的兩種返回值:
A、函數的執行結果返回值:
(1) 使用echo或printf命令進行輸出
(2) 函數體中調用命令的輸出結果
B、函數的退出狀態碼:(一般用于條件判斷時,當滿足條件時,結束函數進程)請見例題2
(1) 默認取決于函數中執行的最后一條命令的退出狀態碼
(2) 自定義退出狀態碼,其格式為:
return 從函數中返回,用最后狀態命令決定返回值
return 0 無錯誤返回。
return 1-255 有錯誤返回
例題:
1、寫一個函數實現兩個數字做為參數,返回最大值
2、寫一個函數實現數字的加減乘除運算,例如輸入1 + 2,,將得出正確結果
(如下圖,需求不同,代碼也不一樣)
11、函數的遞歸:
1、函數遞歸:函數直接或間接調用自身;但需要注意遞歸層數。
2、遞歸實例:
階乘是基斯頓·卡曼于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)!
3、示例:digui.sh
事例:
1、斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列: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階斐波那契數列
代碼和效果如下圖:
從題目中可以得知,從2開始,后一個數值是前兩個數值的之和;因此,$1為1時,值為1;$1為2時,為0+1=1;$1為3時,為1+1=1……
2、漢諾塔(又稱河內塔)問題是源于印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
利用函數,實現N片盤的漢諾塔的移動步驟
代碼和效果如下圖:
三根柱子分別為:A、B、C;
如果沒有圓盤,則輸出為空;
如果只有一個圓盤,則可以直接從柱子A移動到移動C,所以echo $2—$4;
如果有兩個及以上的圓盤,第一步先要借助柱子C將n-1的圓盤移動到柱子B上,因此第一個遞歸ta $(($1-1)) $2 $4 $3(A、C、B),所以是echo $2—-$4(第n個圓盤的移動);第二步是將第一步移動到柱子B上存放的n-1圓盤借助柱子A來調換到柱子C上,即是第二個遞歸ta $(($1-1)) $3 $2 $4,因此,所以是echo $2—-$4
原創文章,作者:Aaron_wang,如若轉載,請注明出處:http://www.www58058.com/37758
文章條理結構清晰,層次分明,圖文并貌,需要注意的地方是,圖片不夠清晰。