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
雙括号範例

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



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

注意紅框的地方

第一章節到此結束,本人水準有限,如有錯漏地方,歡迎指正。
<b>本文轉自 ljpwinxp 51CTO部落格,原文連結:http://blog.51cto.com/191226139/2044393</b>