看了<Unix的設計思想>,不由自主但願從新學習我曾經忽視的linux的shell腳本編程。我並非隨波逐流,也不是那種頑固的技術黨,只是很純粹的想了解這麼技術,若是你有什麼好的想法,也能夠跟我交流,下面是個人微博地址:linux
http://weibo.com/1752090185/profile?rightmod=1&wvr=5&mod=personinfoshell
若是你有跟我同樣的學習熱情,不妨跟我一塊學習下去。編程
先說變量的定義:數組
變量的定義很是的簡單,就是變量名=變量值,中間不加空格。若是你加上空格,那麼shell會認爲這個是一個命令而不是一個語句。而你在引用變量的 時候能夠經過$變量名的方式來引用。其實你也能夠經過${變量名}和$((變量名))的方式來取出它的值。$符號後面將被默認解析成變量,這裏我作了一個 假設,好比你有一個變量爲a,另一個變量爲ab,那麼它取的是a的值仍是ab的值呢?bash
若是出現的是下列這種語句呢?網絡
$abc數據結構
對,應該是沒有這個變量的,它會去查找abc這個變量,而這個變量咱們壓根就沒有定義過.那麼若是咱們必定要取得a這個變量呢?相信你跟我同樣已經有了答案,那就是寫成${a}bc的形式。學習
接下來咱們要說到一個很特別的變量叫作環境變量,環境變量咱們能夠理解爲系統預設的宏,或者常量。固然這麼說可能不合理,由於環境變量是能夠設置的。子進程能夠定義本身的環境變量,父進程會將環境變量的參數傳遞給子進程。測試
環境變量的設置要經過export命令,經過不帶參數的export命令能夠打印出全部的環境變量.也許有人會問,我爲何要用export命令 呢?我用=同樣能夠定義變量。其實是這樣的,咱們本身定義的變量只在進程內有效,是不會傳遞給子進程的。那怎麼測試這樣東西呢?咱們知道在shell執 行的大部分命令都是開啓一個進程,發生了進程的上下文切換,咱們能夠在shell命令行裏面再啓動一個shell做爲上一個shell的子進程。spa
在啓動shell以前咱們先定義兩個變量
param1="david_chen"
export param2="chen_david"
接下來咱們執行一下shell,我這裏使用的是bash,我就執行一下bash
好了,接下來咱們打印一下這兩個參數吧,咱們發現,param1沒有東西,而param2是正常的。
在shell裏面,每一變量的類型咱們均可以理解爲是一個字符串數組,也就是說在shell裏面是沒有類型的,也就是所謂的弱類型語言。
咱們知道咱們學習語言的本質目的是爲了運算,咱們先說一下數學運算.數學運算裏面有三個經常使用的命令:
expr,let 和 bc.
expr,let用於整數運算,而bc用於浮點數運算。
以前咱們提到過{}(())這兩個算子,是用來引用變量的,這裏咱們引入了另一個算子[],這些算子裏面的變量都是能夠不加$的,而能用於算數運 算的是(())和[] 也就是說這兩個基本上是等價的。而在使用這些操做符號的時候必定要注意變量和符號之間要有空格。浮點數咱們就不深究了,有須要我會再回頭來看下資料的。
接下來咱們接着咱們的第二個主題,文件描述符。
其實文件描述符就是一個句柄,或者說是一個字長的整數。其中的三個整數是被系統佔用的也就是0,1,2。它們分別對應着標準輸入,標準輸出和錯誤。重定向的目的就是將這些流的方向從新定向到你但願的地方。你可能將它持久化,多是管道,也多是網絡。
不論咱們是標準輸出,仍是錯誤輸出,咱們都會在屏幕上看到信息,所以咱們能夠看出,實際上標準輸出和錯誤輸出實際上對應的是同一個定向終端文件。也就是屏幕。咱們能夠經過數字來制定文件描述符的定向流。
好比說 2>syserr.log 那麼也就是將2描述符也就是錯誤輸出定向到syserr.log這個文件流中,而1>sysout.log也是同樣的道理。若是你採用這種方法那麼你的標準定向就會發生變化。
命令格式爲:
cmd 2>syserr.log 1>sysout.log
若是你認爲2中的數據沒有你須要的,你能夠定向到一個很特殊的文件 /dev/null中,全部被定向到這個文件中的流都會被丟棄。
接下來我將介紹一個很是重要的數據結構,數組。稱它爲數組可能並不恰當,能夠稱它爲映射表,和其餘的腳本語言很是相似,這裏咱們所說的數組同樣具備映射功能。
數組的定義能夠經過 array=(1 2 3 4)這種方式來定義,通常的腳本都會支持空格和,兩種分割符號,可是在shell裏面只支持空格。這裏咱們仍是能夠引用C語言中的指針思想,其實在 shell腳本中的數組就是一個地址指針。咱們知道,在數組中,數組的指針對應着索引0的位置,我嘗試了一下打印$array:
發現真的如我所願打印出1 那麼對於指針運算是否支持呢?在前面咱們知道對於算數運算的算子是[].我嘗試了一下指針的運算$[ array + 1].如咱們所料的同樣它打印出索引爲1的指針指向數值。咱們能夠類比的推斷出來,其實shell中的數組也是一種指針,經過對指針的運算,實際上獲得的 仍是個指針。與咱們的傳統變量不一樣,傳統變量獲得的是一個具體的值。那就更加奇怪了不是嗎?
咱們在定義一個變量a=1的時候,經過運算$[a+1]獲得的是2,若是a是一個數組,咱們獲得的是一個指針指向值。這兩種大相徑庭的操做只說明一 點。shell是有類型的,咱們姑且能夠認爲有兩種,一種是普通類型,一種是指針類型。不過貌似全部的語言大都是這種模式,只不過對於弱語言來講是後期綁 定的類型。
好的咱們上面講了咱們在取得數組值的時候能夠採用$[a+n]的方法來得到,還有一種是經過${a[n]}的形式來得到索引爲n的值.若是咱們要遍歷整個數組呢?
${array[*]}
這種寫法可讓咱們遍歷整個數組。對於數組長度的運算採用$[#array[*]],就跟咱們的字符串數組同樣。你定義了一個字符串數組a="123"
${#a}就是獲得這個字符串數組的長度。說完索引數組,咱們接着說關聯數組
關聯數組以前是須要調用declare -A testarray來申明關聯數組類型的,我也不知道爲什麼,我但願有了解的讀者能給我個答案。能夠加個人微博@ -非子墨- 來跟我私信。
而後配置你的關聯屬性.對於關聯數組中的key,你不得不給出[]下標,否則可能會出現"爲關聯數組賦值時必須使用下標"這種錯誤。因此關聯數組的格式爲:
([key1]=value1 [key2]=value2)
若是打印keys的話只須要在數組前面加上!符號~估計在數組中除了value就是key吧~~