個人站點:zhangerqing.cn 郵箱:[email protected] 微博:http://weibo.com/xtfggef
Shell腳本就是將很多條命令結合起來寫在一起,通過運算以及判斷來實現很多功能的文本。爲什麼學習shell,首先一些常規的系統管理操作,並且需要自動化地執行,如果用shell腳本把這些操作集中在一起,只需要定期的執行這個shell腳本就可以了,其次,對於一些複雜的文本處理,比如日誌分析等等,可能需求比較多,單條執行命令不是很方便,因此也需要使用shell實現,所以,如果想學通linux系統,shell是必備的一課。本章我們主要以bash shell爲主,不涉及其它shell。
HelloWorld
第一行必須是#!/bin/bash(聲明我們用的是bash shell,否則系統不知道需要調用那個shell去執行腳本)。由#開始的表示註釋,後面的字符在執行的時候全部被忽略。主體就是第4行的echo -e “Hello World \a \n”,-e表示啓用反斜線轉義, \a表示輸出“咚”的聲音,\n表示換行。寫完腳本後,爲腳本添加可執行權限:chmod +x sh01.sh,然後用./sh01.sh執行就好了。
交互式腳本
最簡單的情況就是獲取用戶輸入,然後輸出。
這個例子也比較簡單,實用read進行輸入的獲取,並將值賦於緊跟着的變量上,執行效果:
數值計算
bash shell僅支持整數的簡單加減乘除,需要用到$((express)),兩層小括號內的express則爲計算的表達式。
第七行採用declare的方式聲明一個變量sum,使用$(( ))的方式計算結果。
判斷式
1. test命令
檢查文件是否存在:test -e filename && echo "Exist" || "Not exist",如果存在,會輸出Exist,否則Not exist. test命令有很多參數.
命令 | 參數 | 解釋 | 備註 |
關於文件類型的判斷, test -e filename | |||
test | -e | 文件名是否存在 | 常用 |
-f | 文件名是否存在且爲文件 | 常用 | |
-d | 目錄名是否存在且爲目錄 | 常用 | |
-b | 文件名是否存在且爲一個block device設備 | ||
-c | 文件名是否存在且爲一個character device設備 | ||
-S | 文件名是否存在且爲一個Socket設備 | ||
-p | 文件名是否存在且爲一個FIFO文件 | ||
-L | 文件名是否存在且爲一個連接文件 | ||
關於文件的權限檢測,如test -r filename | |||
-r | 文件名是否存在且具有可讀權限 | ||
-w | 文件名是否存在且具有可寫權限 | ||
-x | 文件名是否存在且具有可執行權限 | ||
-u | 文件名是否存在且具有SUID屬性 | ||
-g | 文件名是否存在且具有SGID屬性 | ||
-k | 文件名是否存在且具有Sticky bit屬性 | ||
-s | 文件名是否存在且爲非空白文件 | ||
關於兩個文件之間的比較,test file1 -nt file2 | |||
-nt | newer than,判斷file1是否比file2新 | 常用 | |
-ot | older than,判斷file1是否比file2舊 | ||
-ef | 判斷file1與file2是否爲同一文件 | ||
關於兩個整數之間的比較,test n1 -eq n2 | |||
-eq | 兩數值相等 | ||
-ne | 兩數值不等 | ||
-gt | greater than,n1 大於n2 | ||
-lt | less than,n1小於n2 | ||
-ge | greater than or equal,n1 大於等於n2 | ||
-le | less than or equal,n1小於等於n2 | ||
判斷字符串 | |||
test -z string | 判斷字符串是否爲0 | ||
test -n string | 判斷字符串是否不爲0 | ||
test str1 = str2 | 判斷字符串是否相等 | ||
test str1 != str2 | 判斷字符串是否不等 | ||
多重條件判定,test -r filename -a -x filename | |||
-a | 兩個條件同時成立時返回true | ||
-O | 任何一個條件成立時返回true | ||
! | 反向狀態,當條件不成立時返回true |
2. []判斷符
除了使用test外,我們還可以使用[](中括號)來進行一些判斷,如判斷HOME環境變量是否爲空:
[ -z $HOME ] ; echo $?
注意命令中的空格,[之後]之前都要跟一個空格,如果用到==,則==兩側也都需要有一個空格(要麼都有,要麼都沒有)。比如,[ "aaa" == "bbb" ],這是合理的方式,如果寫成[ "aaa" =="bbb" ]或者[ "aaa"== "bbb" ]就不合理了,會報錯。使用[]進行判斷時,應該注意如下幾點:
a. 在括號[]內的組件都需要空格來分隔。
b. 括號內的變量最好要用雙引號括起來。
c. 括號內的常量最好也要用單引號或者雙引號括起來。
3. shell script的默認變量$0, $1, $2...
當我們給一個腳本帶參數運行時,我們可以在腳本里獲取到該命令的一些信息,比如:sh01.sh aaa bbb,在腳本里,$0就可以拿到腳本名,$1,$2分別爲第一、第二個參數,以此類推,我們可以總結一下:
$0, 腳本名
$1, $2,腳本的參數
$#, 參數個數
$@, 所有參數,每個參數用雙引號括起來
$*, 所有參數,用空格隔開
做個例子:
運行結果:
條件判斷式
這個好理解,就是我們常見的if else語句,在shell腳本里用if then表示if語句,if then else表示if else語句,if出現時要用fi來結尾,else if用elif代替。看個例子:
1. 判斷輸入的第一個參數是不是hello
2. 如果無任何參數,則提示用戶輸入一個參數
3. 如果輸入的參數不是hello,則提示用戶只能輸入hello作爲參數
查看效果:
case判斷
我們用過程序語言裏的switch case語句,在某些情況下比if else方便很多,在shell腳本里也有類似的語句塊叫:case in esac,還是上面的例子,我們換種寫法:
看看效果:
循環
1. while do ... done
這個就是我們常見的while循環,當滿足條件時,已知執行循環體裏的語句,直到條件不滿足時推出循環,done爲循環結束標誌。
2. until do ... done
該語句和while do ... done正好相反,當條件不滿足時進行循環,滿足時結束循環。
3. for do ... done
常見的for循環,一般就是對一個已知的數組或者結構進行循環遍歷。
for do ... done還有一種用法就是對數值的處理,可以使用我們傳統for循環的方式: for (( ;;))
shell 腳本的追蹤與調試
在執行一個shell腳本之前,我們可以先進行一系列的語法檢查,這樣可以初步檢測出一些明顯的問題。
sh [-nvx] script.sh
-n, 不執行script,僅檢查語法問題
-v, 在執行script前,先輸出腳本到屏幕上
-x, 將使用到的script顯示到屏幕上,列出所有的執行過程
這一章基本就要結束了,主要是一些基本的編寫shell script的語法,我們可以先把這些掌握熟了,多加練習,然後多看一些複雜的文本處理的例子,多學習,多模仿複雜腳本的寫法,然後寫出複雜的腳本就不再是什麼難事。