本文部分資料和示例援引自以下書籍。在此,感謝原作者的創作,以及所有譯者的付出,向他們緻敬。
<a href="http://www.tldp.org/LDP/abs/html/" target="_blank">Advanced Bash-Scripting Guide</a>
<a href="https://linuxstory.gitbooks.io/advanced-bash-scripting-guide-in-chinese/content/" target="_blank">《進階Bash腳本程式設計指南》Revision 10中文版</a>
<a href="https://bash.cyberciti.biz/guide/Main_Page" target="_blank">Linux腳本程式設計執導</a>
第一部分 函數 1. 函數定義 2. 函數使用 3. 函數傳回值 4. 函數參數 5. 函數變量 6. 函數的遞歸調用 第二部分 數組 1. 數組聲明與指派 2. 數組引用 3. 數組的資料處理
函數,任何一門進階程式設計語言中都具備的一種代碼結構。其實是借用了工程上子產品化的思想。函數的作用能夠将簡化代碼的編寫,使得程式結構更加的清晰。同時函數能夠複用重複的代碼,實作代碼重用和子產品化。 bash中函數是由若幹條shell指令組成的語句塊,與shell程式形式上是相似的,不同的是它不是一個單獨的程序,不能獨立運作,而是shell程式的一部分。 函數由兩部分組成:函數名和函數體 ,bash中函數的定義如下所示。
實際使用過程中, 三種方式沒有什麼差別,根據自己的喜好去使用就可以。
函數使用場景一般是在bash腳本中,定義函數,然後進行調用。
同時也推薦,bash 腳本中需要使用的函數全部定義到一個單獨的檔案中,然後在bash腳本中進行引用。這樣做的好處就是不光這一個bash腳本可以引用該檔案裡面的函數,其他的bash腳本也可以引用裡面的某些函數。CentOS典型的例子有很多,例如/etc/init.d/functions檔案。
然後在bash腳本中進行調用
bash中有兩種傳回值 函數執行結果傳回值,使用echo指令傳回,相當于Java 中的return關鍵字。 函數的退出狀态碼,預設是函數體最後一條指令的退出狀态碼。當然也可以自定義,使用return關鍵字。自定義退出狀态碼,其格式為: return 從函數中傳回,用最後狀态指令決定傳回值。 return 0 無錯誤傳回 return 1-255 有錯誤傳回
bash 中函數支援參數的傳遞。但是與其他進階程式設計語言不同的是,bash中并不會顯示的指定參數的類型和個數,而是直接在函數的最後的傳入參數。與bash腳本的參數傳遞是一緻的。 在函數體中當中,可使用$1, $2, …調用這些參數;還可以使用$@, $*, $#等特殊變量。這一點與bash腳本幾乎一緻。
因為bash的寫法太過于靈活,以至于讓人感覺bash并不是很嚴謹,在使用的時候可能要抛棄以往那些進階程式設計語言的思維。上面示例的結果如下圖所示。
bash中的變量的作用域有三種類型: 環境變量:在目前shell和子shell中有效。 本地變量:隻在目前shell程序中有效。 局部變量:隻在函數的生命周期中有效。函數運作結束,變量失效。
在函數中定義局部變量的的方式是 <code>local VARIABLE_NAME=VALUE</code>
函數的遞歸調用指的是,函數間接地或者直接地調用自身。但是在遞歸地同時一定要注意什麼時候結束遞歸,避免死循環。 這是程式設計地一種基本能力。
實驗一 實作斐波那契數列
斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列: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階斐波那契數列
實驗二 實作漢諾塔
漢諾塔(又稱河内塔)問題是源于印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。大梵天指令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次隻能移動一個圓盤,利用函數,實作N片盤的漢諾塔的移動步驟。
實驗三 fork炸彈
fork 炸彈是一種惡意地程式。實質上是一個簡單地遞歸程式,由于程式是遞歸的,如果沒有任何限制,這會導緻這個簡單的程式迅速耗盡系統裡面的所有資源。
順便附上前幾年比較火的讓浏覽器瞬間崩潰的12行代碼,其實原理與fork炸彈是類似的。
bash 中沒有像其他進階程式設計語言那麼多的基本資料類型(int double)和引用資料類型(List ArrayList)。bash是一種弱類型的程式設計語言。 數組是存儲多個元素的連續的記憶體空間,相當于多個變量的集合。
數組的聲明有兩種方式 顯示聲明:<code>declare -a ARRAY_NAME</code> 直接指派:<code>ARRAY_NAME[INDEX]=VALUE</code> ,如果使用這種方式,Bash會自動建立數組。
數組的指派有多種方式 一次隻指派一個元素 <code>ARRAY_NAME[INDEX]=VALUE</code> 一次指派全部元素 <code>ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)</code> 隻指派特定元素 <code>ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)</code>
在介紹了數組的引用之後,一并來舉例說明數組的使用。
注意:索引可支援使用自定義的格式,而不僅是數值格式,即為關聯索引,bash4.0版本之後開始支援,這就是關聯數組,有點類似于進階程式設計語言中的字典
數組的引用有下面幾種方式 <code>${ARRAY_NAME[INDEX]}</code>省略[INDEX]表示引用下标為0的元素 引用所有的元素 <code>${ARRAY_NAME[*]}</code>,<code>${ARRAY_NAME[@]}</code> 數組的長度 <code>${#ARRAY_NAME[*]}</code> ,<code>${#ARRAY_NAME[@]}</code> 删除數組中的某個元素:導緻稀疏格式 ,<code>unset ARRAY[INDEX]</code> 删除整個數組:<code>unset ARRAY</code>
數組資料的處理涉及到了數組資料的讀取和追加。 數組切片 <code>${ARRAY[@]:offset:number}</code> offset :要跳過的元素個數 number:要取出的元素個數 區偏移量之後的所有元素 <code>${ARRAY[@]:offset}</code> 向數組中追加元素 <code>ARRAY[${#ARRAY[*]}]=value</code>
實驗一 實作矩陣轉置
這裡我們需要注意的是,在bash中并沒有二維數組的這個概念。是以我們隻能夠使用自定義下标的方式來模拟二維數組,原理上是相似的。 實作效果如下圖所示。
實驗二 編寫腳本,定義一個數組,數組中的元素是/var/log目錄下所有以.log結尾的檔案;要統計其下标為偶數的檔案中的行數之和
迄今為止,bash程式設計的大部分知識都已經介紹的差不多了,但是介紹的内容比較淺顯,并沒有深入的介紹。同時bash程式設計由于具有巨大的靈活性,導緻使用方式多種多樣,實際生産中應該根據自己的實際情況來靈活使用。
本文轉自Eumenides_s 51CTO部落格,原文連結:http://blog.51cto.com/xiaoshuaigege/1965109,如需轉載請自行聯系原作者