linux shell腳本編程基本語法
Shell script是利用shell的功能所寫的一個“程序”,這個程序是使用純文本文件,將一些Linux Shell的語法與命令(含外部命令)寫在裏面,搭配正則表達式、管道命令與數據流重定向等功能,以達到我們所想要的處理目的。Shell script提供數組、循環、條件與邏輯判斷等重要功能,讓用戶也可以直接以shell來編寫程序,而不必使用類似C程序來完成相關功能。Shell Script就像是早期DOS年代的批處理文件(.bat)。
編程格式
在寫C程序的時候,代碼的開頭我們通常會給版本信息。shell腳本也不例外。
一般聲明如下。
#!/bin/sh
# Program:
# This program shows "Hello World" in your srceen
# History:
# 2017-6-5 liwanneng V1.0.0
echo -e "Hello world"
- 第一行 #!/bin/sh 聲明該shell script使用的shell名稱,linux默認使用的是bash shell
- 第二行Program後面是程序內容的說明,這個shellscript中,除了第一行外,其他#符號表示註釋
- 第四行History後面是時間,作者以及版本信息
- 從echo開始,後面表示程序正文
shell script中常見語法
從屏幕中獲取輸入
在shell script中,使用read -p 來獲取標準輸入
例如
#!/bin/sh
# Program:
# This program User input his first name and last name, Program shows his full name
# History:
# 2017-6-5 liwanneng V1.0.0
read -p "Please input your first name:" firstname #提示用戶輸入,末尾的first爲變量名
read -p "Please input your last name:" lastname
echo -e "/nYour full name is :$firstname $lastname" #結果由屏幕輸出
其輸出結果如圖
數值運算,簡單的加減乘除
在shell script腳本中,可以使用$( (計算式) )來進行整數數值運算
#!/bin/sh
# Program:
# This program
# History:
# 2017-6-5 liwanneng V1.0.0
echo -e "Please Input TWO numbers\n"
read -p "the first number is:" num1#提示用戶輸入,末尾的num1爲變量名
read -p "the second number is:" num2
product=$(($num1*$num2))
sum=$(($num1+$num2))
red=$(($num1-$num2))
div=$(($num1/$num2))
echo -e "$num1 x $num2 = $product"
echo -e "$num1 + $num2 = $sum"
echo -e "$num1 - $num2 = $red"
echo -e "$num1 ÷ $num2 = $div"
結果:
shell script中的默認變量($0, $1…)
在bashshell中,$0表示腳本程序本身,$1表示腳本程序後面跟的第一個參數,以此類推,$2表示腳本程序後面跟的第二個參數。除了這些數字變量之外,還有一些較爲特殊的變量可以在script中使用來調用這些參數。
* $#:表示腳本程序後面跟的參數個數
* \$@:表示 “\$1”, “\$2”, “\$3”之意,每個變量是獨立的。
* \$*:表示”\$1c\$2c\$3”,其中c爲分隔字符,默認爲空格鍵。
來看個例子
#!/bin/sh
# Program
# Program shows script name, paramters...
# History
# 2017-6-4
echo -e "The script name is $0"
echo -e "Total parameter numher is $#"
[ "$#" -lt 2 ] && echo -e "The number of paramter is less than 2. Stop here. " && exit 0
echo -e "Your whole paramter is $@"
echo -e "Your first paramter is $1"
echo -e "Your second paramter is $2"
執行結果
shell script中的判斷
test命令的測試
在linux中,可以使用test命令來測試系統上面某些文件的相關屬性。例如,我要檢查sh01.sh是否存在使用:test -e ./sh01.sh
單獨執行該命令不會顯示任何結果,我們可以在後面加上&&以及||來顯示結果,如圖:
其中 test命令後面跟的 -e表示:判斷文件是否存在。除了-e外,test還可以跟其他許多的參數來獲取文件或變量的相關屬性如
- 關於某個文件名的文件類型判斷,如 test -e filename
-e:該文件名是否存在
-f:該文件名是否存在且爲文件
-d:該文件名是否存在且爲目錄
-b:該文件名是否存在且爲塊設備文件
-c:該文件名是否存在且爲字符設備文件
-S:該文件名是否存在且爲socket文件(大寫S)
-p:該文件名是否存在且爲FIFO文件
-L:該文件名是否存在且爲鏈接文件 - 關於文件的權限檢測,如test -r filename
-r:該文件名是否存在且具有“可讀”權限
-w:該文件名是否存在且具有“可寫”權限
-x:該文件名是否存在且具有“可執行”權限
-u:該文件名是否存在且具有“SUID”屬性
-g:該文件名是否存在且具有“SGID”屬性
-k:該文件名是否存在且具有“sticky bit”屬性
-s:該文件名是否存在且爲“非空白文件”(小寫s) - 兩個文件之間的比較,如:test file1 -nt file2
-nt:newer than,判斷file1是否比file2新
-ot:older than,判斷file1是否比file2舊
-ef:判斷file1與file2是否爲同一文件,可用在判斷hard link的判定上。主要意義在於判定兩個文件是否指向統一個inode - 關於兩個整數之間的判定,如test num1 eq num2
-eq:equal,num1等於num2
-ne:not equal,num1不等於num2
-gt:greater than,num1大於num2
-lt:less than,num1小於num2
-ge:great equal,num1大於等於num2
-le:less equal,num1小於等於num2 - 判定字符串的數據
test -z string:判定字符串是否爲0,若string爲空字符串,則爲true
test -n string:判定字符串是否爲非零,若string爲空字符串,則爲false - 多重條件判定,例如:test -r filename -a -x filename
-a:兩個條件同時成立!例如 test -r file -a -xfile,則file同時具有 r 與 x 權限時,纔回傳true
-o:任何一個條件成立!例如 test -r file -o -x file,則file具有 r 或者 x 權限時,纔回傳true
!:反向狀態!如test !-x file,當file不具有x時,回傳true。
利用判斷符號[]
除了利用test命令判斷外,我們可以利用判斷符號“[]”(英文輸入狀態下的中括號)來進行數據的判斷。這個符號在shell script中經常與if條件判斷搭配使用。
在bash的語法中使用“[]”做判斷必須要注意的幾點
1. 中括號兩端需要空格符來分隔
2. 在中括號[]內每個組件都需要有空格來分隔
3. 中括號內的變量和常量最好都用雙引號括起來
假如我空格號使用“口”符號來表示,那麼在這些地方需要有空格。
口[口"$HOME"口==口"$MAIL"口]口
上面這句話的意思是變量HOME與變量MAIL是否相同的意思,相當於test$HOME=$MAIL
條件判斷式
if… then是shell script中常用到的條件判斷式。簡單來說就是當符合某項條件的時候,就進行某項工作。其格式一般爲
if [ 條件1 ] ; then
程序段
#在shell script中用elif,功能類似於C語言中的else if語句
elif [ 條件2 ]; then
程序段
else
程序段
fi #fi表示if的結束
下面來看一個例子
#!/bin/sh
# Program
# This program shows user's choice
# History
# 2017-6-4 liwanneng V1.0.0
read -p "Please input Y/N:" yn
if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
echo "Clever boy! You will Continue"
exit 0
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
echo "You will interrupt the program!!!"
exit 0
else
echo "Please input Y/y or N/n!"
exit 0
fi
運行結果如下:
利用case…esac判斷
在shell script中除了用if…then語句來判斷,我們還可以使用case…esac來表示多重條件判斷,類似於C語言中的Case語句。其格式爲:
case $變量名稱 in #關鍵字爲case,還有$符號
"第一個變量內容") #每個變量內容用括號括起來,關鍵字則爲小括號
程序段
;; #每個類型的結尾使用英文輸入法狀態下的兩個分號來表示
"第二個變量內容")
程序段
;;
*) #最後一個變量使用*來表示其他值
exit 1
;;
easc #由esac來表示case語句的最終結尾
來看一個例子
#!/bin/sh
# Program
# Program show "hello" from $1...by using case ...esac
# History
# 2017-6-4 10:32:33
case $1 in
"hello")
echo "Hello,how are you!"
;;
"bye")
echo "bye-bye!"
;;
"") #如果沒有輸入
echo "You must input parameter, ex> {$0 someword}"
;;
*)
echo "use $0 {hello or bye}"
;;
esac
來看程序執行的結果
whlie do done,until do done 不定循環
在C語言中,經常用到whle循環和for循環來表示程序的反覆執行。在shell script中同樣有while循環和for循環,只是shell script 中的while和for 的用法與C語言中稍有不同。
while do done不定循環
在shell script中while…done不定循環的常見格式如下
while [ condition ] #中括號內的狀態就是判斷式
do #do是循環的開始
done #done是循環的結束
while的在英語中的意思是“當…時”,所以while…done這種循環表示當condition條件成立時就進行循環,直到condition條件不成立時才停止循環。
來看一個例子
#!/bin/sh
# Program
# Repet quesstion until input correct answer.
# History
# 2017-6-6 liwanneng V1.0.0
while [ "$yn" != "yes" -a "$yn" != "YES" ]
do
read -p "Please input yes/YES to stop this program:" yn
done
echo -e "OK,you input the correct answer."
上面這個程序爲:當滿足條件 “$yn” != “yes” -a “$yn” != “YES” 即輸入不爲yes/YES時,程序一直循環,調用read語句一直等待用戶輸入。當不滿足條件 “$yn” != “yes” -a “$yn” != “YES” 即輸入爲yes/YES時,程序退出循環,調用echo語句。程序執行結果如圖。
until do done不定循環
在shell script中還有一種不定循環 until do done循環,這種循環恰恰與while相反,它是當條件成立時才進行循環,條件不成立時,程序退出循環。其一般格式如下
ubtil [ condition ]
do
程序段
done
同樣來看一個例子
#!/bin/sh
# Program
# Repeat question ubtil user input correct answer
# History
# 2017-6-6 liwanneng V1.0.0
until [ "$yn" == "yes" -o "$yn" == "YES" ]
do
read -p "Please input yes/YES to stop the program:" yn
done
echo -e "Ok,you input correct answer."
程序執行結果和上面有while循環的程序執行結果一樣。但是程序邏輯卻有所區別。當不滿足條件”$yn” == “yes” -o “$yn” == “YES” 即輸入不爲yes或YES的時候,程序一直循環,調用read語句等待用戶輸入。直到滿足條件 “$yn” == “yes” -o “$yn” == “YES” 即輸入爲yes 或 YES的時候,程序退出循環,執行echo語句。
for … do … done固定循環以及數值處理
相對於while,until的循環方式是必須要“符合某個條件”,for循環則是“已經知道要循環幾次”的狀態。它的語法是
for var in con1 con2 con3 #var爲變量,con1,con2,con3分別爲條件1,條件2,條件3
do
程序段
done
上面這段例子的意思是,當變量
2. 第二次循環時,
來看一個具體的例子,加入有三種動物分別是cat,dog,bird,每一行都輸出一種動物,程序可以寫爲:
#!/bin/sh
# Program
# Using for ...loop to print 3 animal
# History
# 2017-6-6 liwanneng V1.0.0
for animal in dog cat bird
do
echo "There is ${animal}..."
done
程序執行結果如下
for… do… done的數值處理
除了上面的方法外,for循環還有另外一種寫法,也就是C語言中for循環的用法,語句如下:
for ( ( 初始值;限定值;執行步長) )
do
程序段
dne
for後面三串內容的意義:
1. 初始值:某個變量在循環中的初始值,比如常見的 i=1;
2. 限定值:當變量在限定值範圍之內,程序一直循環直到超出限定值,如 i<=100;
3. 執行步長:沒做一次循環的變化量,如i = i+1;
來看一個具體的例子,輸入一個數字num,程序做1+2+3…+num運算
#!/bin/sh
# Program
# Caculate 1+2+3+...$(input)
# HIstory
# 2017-6-6 liwanneng V1.0.0
read -p "Please input a num:" num
for(( i=1; i<$num; i=i+1 ))
do
sum=$(($sum+$i))
done
echo "The result of 1+2+3+...$num is:$sum"
來看程序執行結果
function函數功能
在C語言中我們經常自己封裝函數來表示執行同樣功能的一段代碼,在shell script中同樣有function功能。其一般格式爲
function fname(){
程序段
}
fname爲封裝函數的名字,需要注意的是在shell script中不能像C語言一樣現在調用函數之前聲明,然後可在調用函數之後實現其內容,而只能在調用fname之前就要實現其內容。話不多說,來看例子
#!/bin/sh
# Program
# Use function to repeat information
# History
# 2017-6-6 liwanneng V1.0.0
function printit(){
echo -n "Your choice is :" #加上-n可以不斷行繼續在同一行顯示
}
echo "This program will print your selection."
case $1 in
"one")
printit;echo $1 | tr 'a-z' 'A-Z'#將小寫轉換成大寫
;;
"two")
printit;echo $1 | tr 'a-z' 'A-Z'
;;
"three")
printit;echo $1 | tr 'a-z' 'A-Z'
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac
程序執行結果:
shell script的追蹤與調試
是程序就一定有bug,如果程序出了錯,在C語言中我們又自己的調試方法。在shell script中有沒有辦法調試程序呢,答案是有的。我們可以直接以bash的相關參數來進行判斷。sh -n/v/x script.sh
- -n:不要執行script,僅查詢語法是否正確
- -v:執行script之前,先將script的內容輸出到屏幕
- -x:將使用到的script內容顯示到屏幕上(經常用到)
懂了以上這些shell腳本編程語法,一般的shell腳本程序看懂應該沒問題了。但是要想自己會寫shell腳本程序,還得多加練習!多加練習!多加練習!