天天看點

Shell 程式設計基礎(一)

Shell腳本的關鍵在于輸入多個指令并處理每個指令的結果,甚至需要将一個指令的結果傳給另一個指令。Shell可以讓你将多個指令串起來,一次執行完成。

基本格式:

第一行必須為固定格式,指明腳本使用哪種shell來運作腳本,通常shell腳本中會以 # 作為注釋,注釋号後面的内容不會參與腳本的運作,但是,第一行是個例外。

變量命名法則:

1、不能使程式中的保留字:例如if, for

2、隻能使用數字、字母及下劃線,且不能以數字開頭,不能使用 - (減号)

正确:_abc123 ;  abc123 ; abc_123

錯誤:var1-abc=100  ;  var1-123=100  ;  -var1=100

3、見名知義

name  ,date

4、統一命名規則:駝峰命名法

HostName

直接運作腳本的時候,會新開一個shell程序,腳本中預設關閉了alias功能

局部變量:生效範圍為目前shell程序;對目前shell之外的其它shell程序,包括目前shell的子shell程序均無效。

環境(全局)變量:生效範圍為目前shell程序及其子程序

本地變量:生效範圍為目前shell程序中某代碼片斷,通常指函數

位置變量:$1, $2,$N ...來表示,用于讓腳本在腳本代碼中調用通過指令行傳遞給它的參數

特殊變量:

$?

傳回上一條指令執行狀态

$0

指令本身

$*

傳遞給腳本的所有參數,全部參數合為一個字元串,用雙括号括起

$@

傳遞給腳本的所有參數,每個參數為獨立字元串,每個都用雙括号括起

$#

傳遞給腳本的參數的個數

$_

上個指令的最後一個參數

$$

顯示目前程序号

$PPID

顯示父程序号

$!

上一個子程序的程序号

$-

在Shell啟動或使用set指令時提供選項

$n

位置參數值,n表示位置

使用pstree -p 檢視程序樹

$@ $* 隻在被雙引号包起來的時候才會有差異

變量指派:

變量名=值

指派等号與值之間沒有空格

[中括号裡寫變量的時候,記得加雙引号]

(1) 可以是直接字串; 變量名=root  

如果值為帶空格或特殊字元時,請使用雙引号和  \  轉義符号

(2) 變量引用:     變量名="$USER"

(3) 指令引用:    變量名=`指令`

變量名=$(指令)

變量引用:

${變量名}

$變量名

"雙引号":弱引用,其中的變量引用會被替換為變量值

'單引号':強引用,其中的變量引用不會被替換為變量值,而保持原字元串

顯示已定義的所有變量:

set

删除變量:

unset 變量名

隻讀變量:隻能聲明,但不能修改和删除

聲明隻讀變量:

readonly 變量名

declare -r 變量名

檢視隻讀變量:

readonly –p

位置變量:在腳本代碼中調用通過指令行傳遞給腳本的參數

set -- 清空所有位置變量

程序使用退出狀态來報告成功或失敗

一般來講,

0 代表成功,1-255代表失敗

以下表為在未自定義退出狀态碼(exit)時的常見,可以參考

狀态碼

描述

指令成功結束

1

一般性未知錯誤,可能是無效參數

2

不适合的shell指令

126

指令不可執行

127

沒有找到指令

128

無效的退出參數

128+x

與Linux信号x相關的嚴重錯誤

130

通過Ctrl+C終止的指令

255

正常範圍之外的退出狀态碼

bash自定義退出狀态碼

exit [n]:自定義退出狀态碼

腳本中一旦遇到exit指令,腳本會立即終止;終止退出狀态取決于exit指令後面的數字

如果未給腳本指定退出狀态碼,整個腳本的退出狀态碼取決于腳本中執行的最後一條指令的狀态碼

退出狀态可以使用變量作為值,退出狀态碼最大值為255,如果值超過255時,将會通過

取模運算  值/256 把狀态碼縮減到0~255整數值之間,比如:

exit 300

300/256 取模=44    400/256 取模=144

bash自帶腳本測試

bash -n 文法檢查

bash -x  腳本執行按步調試

算術運算

+

兩個整數相加

%

兩整數相除,取餘數

-

第一個數減去第二個數

*

兩整數相乘

\

第一個整數除以第二個整數

實作算術運算的方法:

(1) let 變量名=算術表達式

(2) var=$[算術表達式]

sum=$[uid10+uid20]

sum=$[$uid10+$uid20]

(3) var=$((算術表達式))

sum=$((uid10+uid20))

(4) declare –i 變量名 = 數值

(5) echo ‘算術表達式’ | bc

條件測試

若真,則傳回0

若假,則傳回1

1. test 語句

2. [空格 表達式 空格]

推薦使用第2種方法,因為我們去看系統本身自帶的腳本編寫使用的正是這一類方法。

第一個 [ 之後和第二個 ] 之前必須加上一個空格,否則會報錯

上面的中括号是錯誤的格式,會報以下的錯誤

++++++++++++我是華麗的分界線++++++++++++++++++++

以下才是正确的格式

可以判斷4類條件

a.數值測試 b.字元串測試 c.檔案測試 d.布爾邏輯組合測試條件

以下逐個看

a.數值測試

可以用在數字和變量(變量值是數字)上

-lt

小于

less than

-eq

等于 equal

-gt

大于

great than

-ne

不等于

not equal

-ge

大于等于

great equal

-le

小于等于

less equal

注意,當碰到系統特殊符号的時候,記得 \ 轉義

但是涉及到浮點值的時候,數值測試會有一個限制 ,我們來看一個例子:

變量$var1的值是浮點值,腳本對這個值進行了測試,顯然這裡就報錯。是以,請記住

bash shell隻能處理整數(zshell能很好的解決這個問題),當然,如果這個值隻是用來

echo 輸出是沒問題的。

是以,此時shell的退出狀态碼也是為非0值了,也就是執行了else 之後的語句。

b.字元串測試

相等比較

在比較字元的相等性時,會将所有的标點和大小寫情況都考慮在内的

==

字元串是否相同

-n 字元串

字元串是否為非0

!=

字元串是否不同

-z 字元串

字元串是否為0

<

左邊的ascii碼是否小于右邊的ascii碼

=~

左側字元串是否能夠被

右側的表達式所比對

用于[[ 雙中括号中 ]]

>

左邊的ascii碼是否大于右邊的ascii碼

使用調試工具來直覺的看出狀态碼與結果

使用=或者==  ,或者"" 和"空格" 的結果都是一緻的

使用單引号也是一緻的

這裡需要注意的是,當值中帶有空格的時候,變量沒有雙引号引起來會是報錯的

當變量雙引号引起來的時候,

正确輸出

是以,在寫 bash 腳本的時候,别偷懶,對于變量的引用最好都加上雙引号!就變量引用上來說,雖然 zsh 在這點要強過 bash,但是處于相容性的考慮,還是把雙引号帶上吧。

字元的比較

先來一個初學者常犯的錯誤

乍一看,沒問題啊

可以當然我們使用ls檢視目前目錄的時候,發現$var2的值被重定向至以$var2的值,也就是abcdA的檔案中了。這是一個不易覺察的嚴重問題。腳本把 > 解析成了重定向輸出符号。同時,因為重定向成功,是以exit退出碼為0,就會執行then語句了。

是以,使用 雙引号 引起來 或 \ 轉義解決吧。

這才是規範的腳本寫法,别掉坑了哦~~

這才是正确的輸出結果

字元串的大小寫比較

在Shell的比較測試中,大寫字母是被認為是小于小寫字母的。這一點與sort指令恰好相反,同樣的字元串用sort排序時,小寫字母先出現,這是由于各個指令使用的排序技術不同造成的。

是以,總結為2句話:

shell程式設計時,小寫字母 >(大于) 大寫字母

sort排序時,小寫字母  >(優先) 大寫字母

如果出現以下大小寫混合并相同的情況呢

那麼就從左邊開始比,第一位a相同,那就比第一位,b > A  根據以前的總結,結果就是

$var1 > $var2,不信就以圖驗證下

而sort指令則是以按小寫字母>相同的大寫字母排序的,注意哦~

如果是把數值的比較用了字元串的比較,那麼你會懷疑你的數學是體育老師教的吧

數字越大就是大

最後的總結,如果使用錯了操作符,可能無法得到正确的結果。

比較類型

使用的操作符

數值

-lt; -gt; -le; -ge; -eg; -ne

字元串

=; !=; >; <;

檢查變量是否含有資料

-n 就是判斷字元串是否為0

結果

結果,同時用雙引号引起來的 空格 也是一樣的結果

結果,沒有定義就是0,就是沒有值

-z 就是判斷字元串是否為0

結果,與-n選項的結果是一緻的

結果,用單引号引起來的 空格,結果也是一樣的,與-n的結果是一緻的

結果,用單引号引起來的的什麼也沒有,結果也是一樣的,與-n的結果是一緻的

結果,與-n 的結果是一緻的

最後的總結,不管是單雙引号引用的沒有值變量,或者沒有被聲明的變量,值都是0.也就是空。

空和未初始化的變量會對shell腳本測試造成災難性的影響,如果不是很确定一個變量的内容,最好在将其用于數值或字元串比較之前先通過- n 或 -z 來測試下變量是否含有值。

最後最後的警示示範:

清除下曆史記錄

#history -c

執行腳本,我的天啊,我的腳本原本的意圖隻是想删除/app/下面的全部檔案而已,怎麼變成了删除根目錄下面的全部檔案夾了呢!!太吓人了啊~~腳本有風險,且行且珍惜。哈哈~~

c.檔案測試

用來測試Linux檔案和目錄的狀态。

(選項後接file名,比如 -e file  )

存在性測試

-e

檔案存在性測試,存在為真,否則為假

存在性及類别測試

-b

是否存在且為塊裝置檔案

-c

是否存在且為字元裝置檔案

-d

是否存在且為目錄檔案

-f

是否存在且為普通檔案

-L(大寫)

存在且為符号連結檔案

-p

是否存在且為命名管道檔案

-S(大寫)

是否存在且為套接字檔案

檔案權限測試

-r

是否存在且可讀

-w

是否存在且可寫

-x

是否存在且可執行

檔案特殊權限測試

-u

是否存在且擁有suid權限

-g

是否存在且擁有sgid權限

-k

是否存在且擁有sticky權限

檔案大小測試

-s(小寫)

是否存在且非空

檔案是否打開測試

-t fd

fd檔案描述符是否在某終端已經打開

-N

檔案自從上一次被讀取之後是否被修改過

-O

目前有效使用者是否為檔案屬主

-G

目前有效使用者是否為檔案屬組,隻會檢查預設的主組,而不檢查附加組

所謂的有效使用者就是指,使用特殊的suid權限時,運作此程式的使用者

雙檔案測試

File1 -ef File2

File1是否是File2的硬連結

File1 -nt File2

File1是否新于File2(mtime)。必須确認檔案是存在的,否則會傳回錯誤結果

File1 -ot File2

File1是否舊于File2(mtime)。必須确認檔案是存在的,否則會傳回錯誤結果

因為這些操作符比較統一規範,自己多練習就好了,我就隻給2個例子:

d.布爾邏輯組合測試條件

&&

并且(AND),操作符2邊的條件同時必須滿足才會執行後面的指令,2個條件組合成為真

[[ 條件1 && 條件2 ]]

test模式下使用-a

||

或者(OR),操作符2邊的條件隻能滿足其中一個才會執行後面的指令,2個條件組合成為假

[[ 條件1 || 條件2 ]]

test模式下使用-o

!

! 條件

第一種方式:雙中括号格式

如:[[ -r FILE ]] && [[ -w FILE ]]

[[ -r FILE ]] || [[ -w FILE ]]

第二種方式:必須使用測試指令test進行

如:test [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

test [ -f /bin/cat -o -x /bin/cat ] && cat /etc/fstab

進階特性

bash shell 提供了2項可在if-then語句中使用的進階特性:

a.用于數學表達式的雙括号 ((  ))

不需有将雙括号中表達式裡的運算符轉義

建議括号内2邊加空格

((空格 表達式  空格))

b.用于進階字元串處理功能的雙中括号 [[  ]]

不是所有的shell都支援雙中括号

建議雙中括号内2邊加空格

[[空格 表達式  空格]]

操作符号

va1++

先運算,後自增1

邏輯求反

va1--

先運算,後自減1

~

位求反

++va1

先自加1,後運算

**

幂運算

--va1

先自減1,後運算

<<

左位移

&

位布爾和

>>

右位移

|

位布爾或

邏輯和

雙中括号中後面跟

擴充正規表達式

邏輯或

va1++  (va1--)

自身先和後面的運算式運算,表達式的結果跟自身沒有任何關系,再自身+-1的值賦與以後使用。

例子: a=5 b=2

a++ +b=7   (a+b=7,此時a的值為6)

上條表達式後的下一條表達式a的值已經變化了

a+b=8

++id ( --id)

++a +b =8  (a+1=6,6+b=8,此時a的值為6)

自身先+-1,再和後面的運算式運算,表達式的結果跟自身沒有任何關系,

以後的值就是原先自身先+-1

雙括号範例

Shell 程式設計基礎(一)

雙中括号範例,擴充正規表達式

Shell 程式設計基礎(一)
Shell 程式設計基礎(一)
Shell 程式設計基礎(一)

如果寫成雙等号的話,雙中括号會自動轉化為帶轉義的寫法

Shell 程式設計基礎(一)

注意紅框的地方

Shell 程式設計基礎(一)

第一章節到此結束,本人水準有限,如有錯漏地方,歡迎指正。

<b>本文轉自 ljpwinxp 51CTO部落格,原文連結:http://blog.51cto.com/191226139/2044393</b>