Shell指令碼類似於C語言,它也有固定的語言格式.簡而言之,Shell指令碼就像早期DOS年代的批次檔(.bat),最賤的功能就是將許多命令寫在一起,讓使用者很輕鬆的就能執行一個檔案的Shell指令碼,就能夠一次執行多個命令.
(1)Shell指令碼第一行的格式
#!/bin/sh
符號#!用來指定該指令檔的解析程式,這裡使用的是bin目錄下的sh解析器.當編輯好指令碼後,如果要執行該指令碼,還必須使其具有可執行屬性,即:
chmod + x filename
這樣,該Shell指令碼便可以執行了.如果該Shell指令碼沒有執行許可權,如
chmod - x filename
此時運行該指令碼時,系統提示: bash:./hello.sh:Permission denied
(2)Shell中的注釋
在進行Shell編程時,以#開頭的句子表示注釋,直到這一行結束.如果使用了注釋,即使相當長時間內沒有使用該指令碼,也能在很短的時間內明白該指令碼的作用及工作原理.
(3)使Shell指令碼中斷的命令
可以使用exit命令來使程式中斷,並給系統回傳一個數值.
比如:
#!/bin/bash
echo "hello embeded! /n"
exit 0
系統列印出"hello embeded!"後換行.當執行到exit 0時就離開了指令碼,並且給系統回傳一個0.
(4)執行Shell指令碼的命令
例如:Shell指令碼名為hello.sh
<1>執行方法1: #./hello.sh
<2>執行方法2: #sh hello.sh
(5)Shell中的變數
在Shell指令碼中,變數有兩種,一種是使用者自訂變數,另一種是系統預設變數.
1、使用者自訂變數
在Shell編程中,所有的變數都由字串組成,並且不需要預先對變數進行聲明,即不需要事先聲明變數的類型,如s1.也可以這樣來理解,在Shell編程中,它支援的唯一類型的變數就是字串.
常式1:
Shell指令碼:mythirdscript.sh
#!/bin/sh
num=2
echo "this is the $numnd"
執行結果:
[root@localhost lishuai]# ./mythirdscript.sh
this is the
執行結果並不會列印出"this is the 2nd".可以使用花括弧來告訴Shell,使用者需要列印出變數num的值.
比如: echo "this is the ${num}nd"
執行結果:
this is the 2nd
常式2:數值運算
#/bin/bash
echo "input your first number"
read num1
echo "input your second number"
read num2
total=$(($num1*$num2))
echo "total=$total"
注意數學運算的這種寫法: var=$(()) #兩個括弧或declare -i var,這樣聲明了var是一整型數.
Attention!!!
<1>自訂變數賦值時,"="左右兩邊都不能有空格.
<2>BASH中的語句結尾不需要分號.
<3>若變數內容由使用者決定,可以使用"read"命令從終端鍵盤擷取使用者的輸入值.
比如: #read -p "Please input your name" name
這樣,使用者輸入的內容便儲存在變數name中了.
2、系統預設的變數
<1> $# 傳入指令碼的命令列參數個數
<2> $* 所有命令列參數值,在各個參數值之間留有空格
<3> $0 命令本身(shell檔案名稱)
<4> $1 第一個命令列參數
<5> $2 第二個命令列參數
Shell指令碼:myforthscript.sh
#!/bin/sh
echo "number of vars:"$#
echo "values of vars:"$*
[ -n "$s1" ] && echo "value of var1:"$1
[ -n "$s2" ] && echo "value of var2:"$2
[ -n "$s3" ] && echo "value of var3:"$3
[ -n "$s4" ] && echo "value of var4:"$4
執行結果:
[root@localhost lishuai]# ./myforthscript.sh 1 2 3 4
number of vars:4
values of vars:1 2 3 4
value of var1:1
value of var2:2
value of var3:3
value of var4:4
Attention!!!
Shell指令碼的局部變數
在C語言中有局部變數之說,在Shell指令碼中同樣有局部變數.在變數首次被賦值時加上local關鍵字可以聲明一個局部變數.
Shell指令碼:myfifthscript.sh
#!/bin/sh
hello="var1"
echo $hello
function func1 #使用關鍵字function定義一函數,函數名為func1
{
local hello="var2"
echo $hello
}
func1
echo $hello
執行結果:
[root@localhost lishuai]# ./myfifthscript.sh
var1
var2
var1
若將函數func1內的關鍵字local去掉,則執行結果為:
var1
var2
var2
(6)Shell中的判斷條件
在Shell指令碼中,要檢測系統上某些檔案或相關屬性,可以使用test命令.比如,要檢查/home/lishuai是否存在,可以這樣來編寫一指令碼或命令.
#!/bin/bash
test -e /home/lishuai && echo "exit" || echo "not exit"
1.符號"&&"緊接在條件判斷語句的後面,表示如果條件為真,則執行"&&"後面的語句.
2.符號"||"緊接在條件判斷語句的後面,表示如果條件為假,則執行"||"後面的語句.
Shell中的測試標誌
(1)某個檔案名稱的"類型"檢測(存在與否),如test -e filename
<1> -e 該檔案名稱是否存在
<2> -f 該檔案是否普通檔案(-)
<3> -d 該檔案是否一個目錄(d)
<4> -b 該檔案是否為一個塊裝置檔案
<5> -c 該檔案是否為一個字元裝置檔案
<6> -L 該檔案是否為一個連結檔案
在Linux系統中,"-"表示普通檔案,"d"表示目錄檔案,"c"表示裝置檔案.
(2)檔案的許可權檢測,如test -r filename
<1> -r 檢測檔案名稱對目前使用者是否具有"可讀"許可權
<2> -w 檢測檔案名稱對目前使用者是否具有"可寫"許可權
<3> -x 檢測檔案名稱對目前使用者是否具有"可執行"許可權
<4> -s 檔案大小不為0
(3)兩個整數之間的判斷,如test n1 -eq n2
比較操作 整數操作 字串操作
相同 -eq =
不同 -ne !=
大於 -gt >
小於 -lt >
大於或等於 -ge
小於或等於 -le
為空白 -z
不為空白 -n
常式:
比較整數a和b是否相等 if [ $a = $b ] (也可用eq)
判斷整數a是否大於整數b if [ $a -gt $b ]
比較字串a和b是否相等 if [ $a = $b ]
判斷字串a是否為空白 if [ -z $a ]
判斷整數變數a是否大於b if [ $a -gt $b ]
(4)多重條件判斷,如test -r filename -a -x filename
<1> -a 兩個條件同時成立,如test -r file -a -x file,則file同時具有r與x許可權時返回true
<2> -o 兩個條件任何一個成立,如test -r file -o -x file,則file具有r或x許可權時返回true
<3> ! 條件求反,如test ! -x file,則file不具備x許可權時返回true
(7)判斷符號[]
除了test外,還可以使用判斷符號[]來進行資料的判斷.其中,中括弧[]的使用方法與test幾乎完全一致,只是中括弧多用在條件判斷語句if...then...fi中.
Attention!!!
判斷符號[]中每個組件中間都要用空格來分隔,比如:
#name="lishuai"
# [ "$name" == "lishuai" ]
1.第一個方括弧的左右兩邊分別有一個空格,第二個方括弧的左右兩邊也分別有一個空格,符號"=="與兩邊的組件之間也各有一個空格.
2.中括弧[]內的變數最好用雙引號來設定.
3.中括弧[]內的常量最好用雙引號或單引號來設定.
4.在Shell指令碼語言中,"=="用於判斷邏輯運算式,是"比較";"="用於給變數設定內容,是"設定".
(8)條件判斷(if...then...語句)
Attention!!!
在Shell指令碼中,&&和||的含義不同.
(1) &&表示AND
(2) ||表示or
條件判斷if...then...語句是Shell指令碼語言中邏輯控制語言,它有三種常用寫法:
(1)第一種格式:類似於C語言的if語句,只需要一個fi表示if語句的結束.
if [ 條件判斷運算式 ]; then
#當條件判斷運算式成立時,可以執行的命令
fi
(2)第二種格式:類似於C語言的if...else語句,只需要一個fi表示if語句的結束
if [ 條件運算式 ]; then
#當條件判斷運算式成立時,可以執行的命令
else
#當條件判斷運算式不成立時,可以執行的命令
fi
(3)第三種格式:類似於C語言的if...else if...else...
if [ 條件運算式1 ]; then
#當條件運算式1成立時,可以執行的命令
elif [ 條件運算式2 ]; then
#當條件運算式2成立時,可以執行的命令
else
#當條件運算式1和2均不成立時,可以執行的命令
fi
(9)條件判斷(case...esac語句)
這種條件判斷類似於C語言中的switch...case...語句,其格式為:
case $變數名 in
"第一個變數內容")
程式段
;;
"第二個變數內容")
程式段
;;
*)
不包含第一個變數內容與第二個變數內容的其它程式執行段
exit 1
;;
esac
Attenton!!!
(1)case語句最後必須以esac為結尾.
(2)每一個變數內容的程式段最後都需要兩個分號來表示該程式段的結束.
(3)最後的"*"作用類似於C語言中的default.
(10)函數在Shell中的應用
函數在Shell指令碼中可以簡化很多程式碼.在Shell指令碼中,函數必須先定義再調用,且必須在程式的最前面來定義,這樣才能在執行時找到可用的程式段.它有固定的定義格式:
function 函數名() {
程式段
}
Attention!!!
函數兩邊的大括弧不能在同一行.
(11)迴圈(while...do...done、until...do...done)
兩種迴圈的區別:while是為真時執行,until是為假時執行.
(1)迴圈while...do...done的格式
當condition條件成立時,就進行迴圈,直到condition的條件不成立才停止.
while [ condition ]
do
程式段
done
(2)迴圈until...do...done的格式
當condition條件成立時就終止迴圈,否則就持續執行迴圈的程式段.
until [ condition ]
do
程式段
done
(12)迴圈(for...do...done)
for迴圈結構與C語言中有所不同,在BASH中for迴圈有兩種基本結構:
基本結構1:
for (( 初始值; 限制值; 執行步長 ))
do
程式段
done
Attention!!!
<1>這種寫法主要用於數值運算.
<2>從上面的for格式可以看出,各個組件之間分別用空格分隔.其實也可以不用這些空格,但建議使用.
基本結構2:
for var in con1 con2 con3 ...
do
程式段
done
Attention!!!
<1>$var是迴圈控制變數,[list]是var需要遍曆的一個集合,do/done對包含了迴圈體,相當於C語言中的一對大括弧.另外,如果do和for被寫在同一行,必須在do前面加上";",
如 for $var in [list];do
<2>for迴圈語句執行過程:
將[list]中的每一個值賦給變數$var,然後執行程式段的操作.
第1次迴圈時,$var的內容是con1
第2次迴圈時,$var的內容是con2
第3次迴圈時,$var的內容是con3
第4次迴圈時,... ...
<3>注意,在for所在的那一行,變數day是沒有加"$"符號的,而在迴圈體內,echo所在行變數day必須加上"$"符號.這是因為在for所在的那一行是對變數day的賦值,而不是引用.在Linux中,只有對變數的引用時才加上"$"符號.
(13)Shell指令碼的追蹤與調試
指令碼在執行之前就怕出問題.Linux提供了不需要通過直接執行該指令碼就判斷是否有問題.
[root@localhost lishuai]# sh [-nvx] scripts.sh
參數:
-n 不執行指令碼,僅檢查文法問題
-v 在指令碼執行前,先將指令碼的內容輸出到螢幕上
-x 將使用的指令碼內容顯示到螢幕上,這個參數最有用.
比如:有一指令檔test.sh,在運行該指令碼前害怕出問題,可以使用Linux提供的途徑來檢查該指令碼是否有問題.
[root@localhost lishuai]# sh -x test.sh
-x參數可以在執行前列出所有要執行的程式段.如果是程式段,則輸出時最前面會加上"+"符號,表示它是程式段.
Attention!!!
Linux中有大量的指令檔,若不直到該指令碼的功能,可以使用vim編輯器開啟該指令檔,通過系統對它的描述(description)就可以明白了.