一、bash 簡介
爲什麼要學習 bash 編程呢?因爲 bash 是每個 Linux 發行版都帶有的一個標準基礎軟件,所以學會在 bash 下編制一些小程序就可以讓你對 Linux 系統的管理應付自如;其次 bash 非常簡單,比起C語言,Java這些,bash還是要簡單很多;最後即使你不打算用 bash 編程,但是 Linux 系統中的許多配置文件和腳本都是 bash 的語法,不懂一點 bash 的知識就不能很好的理解和使用 Linux 。其實最簡單的 bash 就和 DOS 下的批處理文件類似,只要把要執行的命令一行一行寫出來就行。
二、bash的特點
Bourne Again shell (bash), 正如它的名字所暗示的,是 Bourne shell 的擴展。BASH 與 Bourne shell 完全向後兼容,並且在 Bourne shell 的基礎上增加和增強了很多特性。BASH 也包含了很多 csh 和 Korn Shell 裏的優點,使得BASH 有很靈活和強大的編程接口,同時又有很友好的用戶界面。爲什麼要用BASH 來代替 sh 呢?Bourne Shell 最大的缺點在於它處理用戶的輸入方面,在Bourne shell 裏鍵入命令會很麻煩,尤其當你鍵入很多相似的命令時,而 BASH準備了幾種特性使命令的輸入變得更容易。 BASH 的新功能包括 命令補齊、通配符、命令歷史記錄、別名等。
BASH 是一種解釋執行的語言,我們還見過其他一些解釋性的語言,如 BASIC 語言、Perl 語言、TCL/TL 等等。解釋執行的語言的與編譯型語言(如 C 語言)的最大不同就在於運行速度和使用方便程度上。BASH 和後面我們要講解的 Perl語言都是解釋性語言,他們編寫起來很方便,也很快捷,但是由於是解釋執行,所以運行速度和效率必將大打折扣。故而今天介紹的 BASH 和 Perl 這兩種解釋性語言最好的用途就是一些用於完成特定功能的常用的小工具或小程序,對於一些大型的項目、計算複雜的工程或有高級需求的應用還是用 C 語言甚至彙編語言比較好。
下面給出一些 BASH所不適用的範圍:
資源型敏感,對 CPU 負擔重的程序
複雜的大項目
需要靈活處理文件的程序,BASH 只能逐行讀出文件進行處理
需要圖形用戶界面的程序
需要直接與系統硬件打交道的程序
要訪問 I/O 端口和網絡套接字的程序
需要使用庫或和以前的其他代碼整合的程序
三、BASH 的基本語法
1、最簡單的例子 —— Hello World!
#!/bin/bash # This is a very simple example echo Hello World
第一行:#/bin/bash(shebang),在 BASH 中 第一行的 "#!" 及後面的 "/bin/bash" 就表明該文件是一個 BASH 程序,需要由 /bin 目錄下的 bash 程序來解釋執行。
第二行:就是 BASH 程序的註釋,在 BASH 程序中從“#”號(注意:後面緊接着是“!”號的除外)開始到行尾的多有部分均被看作是程序的註釋。
第三行:echo 語句的功能是把 echo 後面的字符串輸出到標準輸出中去。由於 echo 後跟的是 "Hello World" 這個字符串,因此 "Hello World"這個字串就被顯示在控制檯終端的屏幕上了。
需要注意的是 BASH 中的絕大多數語句結尾處都沒有分號。
2、運行腳本的兩種方式
(1)、顯式制定 BASH 去執行:
bash hello.sh
(2)、讓它成爲可執行文件後運行:
chmod +x hello.sh ./hello.sh
3、bash的變量類型
本地變量:作用域爲當前shell進程
varname=value
環境變量:作用域只對當前代碼段有效
export varname=value
局部變量:作用域只對當前代碼段有效
local varname=value
位置變量
$1, ..., $n, ${10}
特殊變量:
$?:狀態返回值
$#: 傳遞給腳本參數的個數
$@ | $*:引用傳遞給腳本的所有參數,但是它們兩者還是有區別的
$0:表示命令本身
4、bash的算術運算
實現算術運算的方式:
let VAR_NAME=ARITHMATIC_EXPRESSION(算術表達式) 也是表達式,但是不可以直接引用,必須要賦值給變量之後纔可以 VAR_NAME=$[ARITHMATIC_EXRESSION](個人常用) VAR_NAME=$((EXPRESSION)) VAR_NAME=$(expr $num1 + $num2) 必須加空格,不然會語法錯誤
算術運算符:
+ - * / %:取模,取餘數 **: 2**2 兩個*號取多少次方
5、bash的賦值
賦值:
a=4
增強型賦值:
+=, -=, *=, /=, %=
6、bash的條件測試
語法
test EXPR
[ EXPR ]
` EXPR `
整型測試:
-gt: 大於 例如 [ $num1 -gt $num2 ] -lt: 小於 -ge: 大於等於 -le: 小於等於 -eq: 等於 -ne: 不等於
字符串測試:
雙目 > 大於 [[ "$str1" > "$str2" ]] < 小於 >= 大於等於 <= 小於等於 == 等於 != 不等於 單目: -n String: 是否不空,不空則爲真,空則爲假 -z String: 是否爲空,空則爲真,不空則假
文件測試:
-a FILE -e FILE: 存在則爲真;否則則爲假; -f FILE: 存在並且爲普通文件,則爲真;否則爲假; -d FILE: 存在並且爲目錄文件,則爲真;否則爲假; -L/-h FILE: 存在並且爲符號鏈接文件,則爲真;否則爲假; -b: 塊設備 -c: 字符設備 -S: 套接字文件 -p: 命名管道 -s FILE: 存在並且爲非空文件則爲值,否則爲假; -r FILE:文件有讀權限爲真,否則爲假 -w FILE:文件有寫權限爲真,否則爲假 -x FILE:文件有執行權限爲真,否則爲假 file1 -nt file2: file1的mtime新於file2則爲真,否則爲假; file1 -ot file2:file1的mtime舊於file2則爲真,否則爲假;
7、bash的循環語句
for語句 格式1: for VAR_NAME in LIST do 循環體 done 格式2: for VAR_NAME is LIST; do 循環體; done 例子:創建10個用戶,user301, user310 for userNo in $(seq 301 310); do useradd user${userNo} done for的第二種使用(c語言風格): for ((初始條件;測試條件;修改表達式)); do 循環體 one while格式: while 測試條件; do 循環體 done 測試條件爲真,進入循環;測試條件爲假,退出循環; 測試條件一般通過變量來描述,需要在循環體不變量地改變變量的值,以確保某一時刻測試條件爲假,進而結束循環; until格式: until 測試條件; do 循環體 done 測試條件爲假,進入循環;測試條件爲真,退出循環; 測試條件一般通過變量來描述,需要在循環體不變量地改變變量的值,以確保某一時刻測試條件爲真,進而結束循環;
8、bash的判斷條件
if判斷條件
單分支的if語句: if 測試條件; then 選擇分支 fi 雙分支的if語句: if 測試條件; then 選擇分支1 else 選擇分支2 fi 多分支的if語句: if 條件1; then 分支1 elif 條件2; then 分支2 elif 條件3; then 分支3 ... else 分支n fi
case語句:有多個測試條件時,case語句會使得語法結構更明晰
case 變量引用 in PATTERN1) 分支1 ;; PATTERN2) 分支2 ;; ... *) 分支n ;; esac PATTERN:類同於文件名通配機制,但支持使用|表示或者; a|b: a或者b *:匹配任意長度的任意字符 ?: 匹配任意單個字符 []: 指定範圍內的任意單個字符 例如:用戶鍵入字符後判斷其所屬的類別; #!/bin/bash # read -p "Plz enter a char: " char case $char in [0-9]) echo "a digit" ;; [a-z]) echo "a char" ;; *) echo "a special word" ;; esac
9、bash編程函數
函數就是模塊化,代碼重用
語法:
function F_NAME {
函數體
}
F_NAME() {
函數體
}
可調用:使用函數名
函數名出現的地方,會被自動替換爲函數;
bash腳本:默認整個腳本就是入口,沒有要求必須做成函數化
函數的返回值:
函數的執行結果返回值:代碼的輸出
函數中的打印語句:echo, print
函數中調用的系統命令執行後返回的結果
執行狀態返回值:
函數體中最後一次執行的命令狀態結果
自定函數執行狀態的返回值:return #
函數可以接受參數:
在函數體中調用函數參數的方式同腳本中調用腳本參數的方式:位置參數
$1, $2, ...
$#, $*, $@
示例:服務腳本示例
#!/bin/bash # # chkconfig: 2345 67 34 # srvName=$(basename $0) lockFile=/var/lock/subsys/$srvName start() { if [ -f $lockFile ];then echo "$srvName is already running." return 1 else touch $lockFile [ $? -eq 0 ] && echo "Starting $srvName OK." return 0 fi } stop() { if [ -f $lockFile ];then rm -f $lockFile &> /dev/null [ $? -eq 0 ] && echo "Stop $srvName OK" && return 0 else echo "$srvName is not started." return 1 fi } status() { if [ -f $lockFile ]; then echo "$srvName is running." else echo "$srvName is stopped." fi return 0 } usage() { echo "Usage: $srvName {start|stop|restart|status}" return 0 } case $1 in start) start ;; stop) stop ;; restart) stop start ;; status) status ;; *) usage exit 1 ;; esac
這些就是bash的基本語法知識啦!!!