Linux Shell指令碼程式設計提高(12)
實際上Shell是一個命令直譯器,它解釋由使用者輸入的命令並且把它們送到核心,不僅如此,Shell有自己的程式語言用於對命令的編輯,它允許使用者編寫由shell命令組成的程式.Shel程式語言具有普通程式語言的很多特點,比如它也有迴圈結構和分支控制結構等,用這種程式語言編寫的Shell程式與其他應用程式具有同樣的效果,下面我們會介紹Shell-Script的編寫.
Shell 條件判斷
◆按檔案型別判斷◆
1.使用 [] 來執行判斷,並使用echo $? 判斷執行結果
[[email protected] ~]# ls
lyshark.log passwd.awk
[ [email protected] ~]# [ -e ./lyshark.log ]
[[email protected] ~]# echo $? #返回0表示檔案 ./lyshark.log 存在
0
[[email protected] ~]# [ -e ./shar ] #返回1表示檔案 ./shar 不存在
[[email protected] ~]# echo $?
1
2.我們可以結合之前所學的 && 和 || 實現判斷後輸出判斷結果
[[email protected] ~]# ls
lyshark.log passwd.awk
[ [email protected] ~]# [ -e ./lyshark.log ] && echo "check ok" || echo "None"
check ok
[[email protected] ~]# [ -e ./shar ] && echo "check on" || echo "None"
None
◆按檔案許可權判斷◆
1.使用 -r 判斷檔案是否可讀,和可執行
[[email protected] ~]# ls
lyshark.log passwd.awk
[[email protected] ~]# [ -r ./lyshark.log ] && echo "check ok" || echo "None"
check ok
[ [email protected] ~]# [ -x ./lyshark.log ] && echo "check ok" || echo "None"
None
[[email protected] ~]# [ -r ./lyshark.log ] && [ -x ./lyshark.log ] && echo "可讀,可執行" || echo "可讀,不可執行" || echo
"不可讀,不可執行"
可讀,不可執行
◆兩檔案之間的比較◆
1.通過 -ef 判斷是否是相同的I節點
[[email protected] ~]# ls -li
total 0
8409155 -rw-r--r-- 2 root root 0 Sep 25 21:39 lyshark_ln.log
8409155 -rw-r--r-- 2 root root 0 Sep 25 21:39 lyshark.log
[[email protected] ~]# [ ./lyshark.log -ef lyshark_ln.log ] && echo "ok" || echo "no"
ok
◆數值之間的比較◆
1.比較兩數字,大小關係
[[email protected] ~]# [ 23 -ge 24 ] && echo "23 >= 24 " || echo "23 <= 24"
23 <= 24
[[email protected] ~]# [ 30 -ge 24 ] && echo "30 >= 24 " || echo "30 <= 24"
30 >= 24
◆字串之間的比較◆
1.字串之間的比較例子,字串是否為空
[[email protected] ~]# name=LyShark
[[email protected] ~]# age=""
[[email protected] ~]# unset sex
[[email protected] ~]# [ -z "$name" ] && echo "字串空" || echo "不為空"
不為空
[[email protected] ~]# [ -z "$age" ] && echo "字串空" || echo "不為空"
字串空
[[email protected] ~]# [ -z "$sex" ] && echo "字串空" || echo "不為空"
字串空
2.兩個字串相等比較
[[email protected] ~]# x=100
[[email protected] ~]# y=200
[[email protected] ~]# z=100
[[email protected] ~]# [ "x" == "y" ] && echo "yes" || echo "no"
no
[[email protected] ~]# [ "$x" == "$y" ] && echo "yes" || echo "no"
no
[[email protected] ~]# [ "$x" == "$z" ] && echo "yes" || echo "no"
yes
◆多重條件判斷◆
1.邏輯與:判斷變數x不為空,並且x大於20
[[email protected] ~]# declare -i x=10
[[email protected] ~]# [ -n "$x" -a "$x" -gt 20 ] && echo "yes" || echo "no"
no
[[email protected] ~]# declare -i x=30
[[email protected] ~]# [ -n "$x" -a "$x" -gt 20 ] && echo "yes" || echo "no"
yes
2.邏輯非:判斷x變數不為空,或!取反
[[email protected] ~]# declare -i x=30
[[email protected] ~]# [ -n "$x" ] && echo "yes" || echo "no"
yes
[[email protected] ~]# [ ! -n "$x" ] && echo "yes" || echo "no"
no
IF條件判斷
if、then、else語句用於判斷給定的條件是否滿足,並根據測試條件的真假來選擇相應的操作.if/else僅僅用於兩分支判斷,多分支的選擇時需要用到if/else語句巢狀、if/elif/else和case多分支選擇判斷結構.
IF結構例子: 一個就簡單的單分支結構.測試條件後如果沒有";"則then語句要換行.
#!/bin/sh
echo "Please input a Number:"
read Num
if [ "$Num" -lt 15 ]
then
echo "$Num <= 15"
fi
IF/IF-ELSE結構: 一個雙分支結構,如下執行刪除檔案,成功返回then是否返回else.
#!/bin/sh
echo "Please input the file which you want to delete:"
read file
if rm -f "$file"
then
echo "Delete the file $file sucessfully!"
else
echo "Delete the file $file failed!"
fi
IF/ELSE巢狀: 可同時判斷三個或三個以上條件,但要注意if與else配對關係,else語句總是與它上面最近的未配對的if配對.
#!/bin/bash
#提示使用者輸入分數(0-100)
echo "Please Input a integer(0-100): "
read score
#判斷學生的分數類別
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
echo "The score what you input is not integer or the score is not in (0-100)."
else
if [ "$score" -ge 90 ]
then
echo "The grade is A!"
else
if [ "$score" -ge 80 ]
then
echo "The grade is B!"
else
if [ "$score" -ge 70 ]
then
echo "The grade is C!"
else
if [ "$score" -ge 60 ]
then
echo "The grade is D!"
else
echo "The grade is E!"
fi
fi
fi
fi
fi
IF/ELIF/ELSE結構: if/else巢狀在程式設計中很容易漏掉then或fi產生錯誤,而且可讀性很差,因此引入if/elif/else結構針對某一事件的多種情況進行處理,fi只出現一次,可讀性也提高了.
#!/bin/bash
echo "Please Input a integer(0-100): "
read score
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
echo "The score what you input is not integer or the score is not in (0-100)."
elif [ "$score" -ge 90 ]
then
echo "The grade is A!"
elif [ "$score" -ge 80 ]
then
echo "The grade is B!"
elif [ "$score" -ge 70 ]
then
echo "The grade is C!"
elif [ "$score" -ge 60 ]
then
echo "The grade is D!"
else
echo "The grade is E!"
fi
例項1: 通過單分支判斷磁碟是否已滿.
[[email protected] ~]# cat if.sh
#!/bin/bash
ret=$( df -h | grep "/dev/sda1" | awk '{printf $5}' | cut -d "%" -f 1 )
if [ $ret -ge 80 ]
then
echo -e "/dev/sda1 is full !!"
fi
例項2: 通過多分支判斷磁碟是否已滿.
[[email protected] ~]# cat if.sh
#!/bin/bash
ret=$( df -h | grep "/dev/sda1" | awk '{printf $5}' | cut -d "%" -f 1 )
if [ $ret -ge 80 ]
then
echo -e "/dev/sda1 is full !"
else
echo -e "/dev/sda1 is not full !"
fi
例項3: 多分支判斷小例子.
[[email protected] ~]# cat if.sh
#!/bin/bash
read -p "輸入一個數字:" num
if [ "$num" -gt "100" ]
then
echo -e "這個數大於100"
elif [ "$num" -lt "100" ]
then
echo -e "這個數小於100"
elif [ "$num" -eq "100" ]
then
echo -e "這個數等於100"
fi
例項4: 判斷輸入的年份是否是潤年(潤年條件:1、能被4整除,但不能被100整除的年份.2、能被100整除,又能被400整除的年份)
#!/bin/sh
echo "Please Input a year: "
read year
let "n1=$year % 4"
let "n2=$year % 100"
let "n3=$year % 400"
if [ "$n1" -ne 0 ]
then
leap=0
elif [ "$n2" -ne 0 ]
then
leap=1
elif [ "$n3" -ne 0 ]
then
leap=0
else
leap=1
fi
CASE分支結構
case結構變數值依次比較,遇到雙分號則跳到esac後的語句執行,沒有匹配則指令碼將執行預設值*
"後的命令,直到"';;"為止.case的匹配值必須是常量或正則表示式.
#!/bin/bash
read -p "輸入一個符號:" temp
case $temp in
"-print")
echo -e "您執行了print函式"
;;
"-save")
echo -e "您執行了save函式"
;;
"-help")
echo -e "您執行了help函式"
;;
*)
echo -e "您執行了其他操作"
;;
esac
FOR迴圈結構
Shell程式設計中迴圈命令用於特定條件下決定某些語句重複執行的控制方式,有三種常用的迴圈語句:for、while和until.while迴圈和for迴圈屬於"當型迴圈",而until屬於"直到型迴圈",迴圈控制符:break和continue控制流程轉向.
列表FOR迴圈: 迴圈列印資料分別從1遍歷到5.
do和done之間的命令稱為迴圈體,執行次數和list列表中常數或字串的個數相同.for迴圈,首先將in後list列表的第一個常數或字串賦值給迴圈變數,然後執行迴圈體,以此執行list,最後執行done命令後的命令序列.
#!/bin/bash
for tmp in {1..5}
do
echo "Hello, Welcome $tmp times"
done
FOR迴圈累加: 通過FOR迴圈累加列印資料.
通過i的按步數2不斷遞增,計算sum值為2500.同樣可以使用seq命令實現按2遞增來計算1~100內的所有奇數之和,for i in $(seq 1 2 100)
,seq表示起始數為1,跳躍的步數為2,結束條件值為100.
#!/bin/bash
sum=0
for i in {1..100..2}
do
let "sum+=i"
done
echo "sum=$sum"
FOR迴圈遍歷目錄: 通過for迴圈顯示當前目錄下所有的檔案.
#!/bin/bash
for file in $( ls )
#for file in *
do
echo "file: $file"
done
不帶列表FOR: 由使用者制定引數和引數的個數,與上述的for迴圈列表引數功能相同.
#!/bin/bash
echo "number of arguments is $#"
echo "What you input is: "
for argument
do
echo "$argument"
done
C風格FOR迴圈: 也被稱為計次迴圈.
#!/bin/bash
for((integer = 1; integer <= 5; integer++))
do
echo "$integer"
done
例項1: 通過for迴圈列印1-10.
[[email protected] ~]# cat for.sh
#!/bin/bash
for temp in `seq 1 10`
do
echo -e "列印資料: $temp"
done
例項2: 通過for迴圈計算1-100的累加和.
[[email protected] ~]# cat for.sh
#!/bin/bash
declare -i sum=0
for temp in `seq 1 100`
do
sum=$sum+$temp
done
echo -e "從1+到100的結果是: $sum"
例項3: 從列表中選擇資料.
[[email protected] ~]# cat for.sh
#!/bin/bash
for temp in 1 3 5 7 9
do
echo -e "列印: $temp"
done
[[email protected] ~]# bash for.sh
列印: 1
列印: 3
列印: 5
列印: 7
列印: 9
例項4: 讀取檔案內容並列印.
[[email protected] ~]# cat for.sh
#!/bin/bash
world=`cat /etc/passwd`
for temp in $world
do
echo -e "列印: $temp"
done
WHILE 迴圈
也稱為前測試迴圈語句,重複次數是利用一個條件來控制是否繼續重複執行這個語句.為了避免死迴圈,必須保證迴圈體中包含迴圈出口條件即表示式存在退出狀態為非0的情況.
計數控制: 指定了迴圈的次數500,初始化計數器值為1,不斷測試迴圈條件i是否小於等於100.在迴圈條件中設定了計數器加2來計算1~100內所有的奇數之和.
#!/bin/bash
sum=0
i=1
while(( i <= 100 ))
do
let "sum+=i"
let "i += 2"
done
echo "sum=$sum"
結束標記控制的while迴圈: 設定一個特殊的資料值(結束標記)來結束while迴圈.
#!/bin/bash
echo "Please input the num(1-10) "
read num
while [[ "$num" != 4 ]]
do
if [ "$num" -lt 4 ]
then
echo "Too small. Try again!"
read num
elif [ "$num" -gt 4 ]
then
echo "To high. Try again"
read num
else
exit 0
fi
done
echo "Congratulation, you are right! "
標誌控制的while迴圈: 使用使用者輸入的標誌值來控制迴圈的結束(避免不知道迴圈結束標誌的條件).
#!/bin/bash
echo "Please input the num "
read num
sum=0
i=1
signal=0
while [[ "$signal" -ne 1 ]]
do
if [ "$i" -eq "$num" ]
then
let "signal=1"
let "sum+=i"
echo "1+2+...+$num=$sum"
else
let "sum=sum+i"
let "i++"
fi
done
命令列控制的while迴圈: 使用命令列來指定輸出引數和引數個數,通常與shift結合使用,shift命令使位置變數下移一位($2代替$1、$3代替$2,並使$#變數遞減
),當最後一個引數顯示給使用者,$#
會等於0,$*
也等於空.
#!/bin/bash
echo "number of arguments is $#"
echo "What you input is: "
while [[ "$*" != "" ]]
do
echo "$1"
shift
done
while計算: 通過while迴圈,計算1-100的累加和.
[[email protected] ~]# cat while.sh
#!/bin/bash
declare -i x=0
declare -i num=0
while [ "$x" -lt "100" ]
do
x=$x+1
num=$num+$x
done
echo -e "從1-100結果是: $num"
[[email protected] ~]# bash while.sh
從1-100結果是: 5050
UNTIL 迴圈
until命令和while命令類似,while能實現的指令碼until同樣也可以實現,但區別是until迴圈的退出狀態是不為0,退出狀態是為0(與while剛好相反),即whie迴圈在條件為真時繼續執行迴圈而until則在條件為假時執行迴圈.
#!/bin/bash
i=0
until [[ "$i" -gt 5 ]] #大於5
do
let "square=i*i"
echo "$i * $i = $square"
let "i++"
done
#!/bin/bash
for (( i = 1; i <=9; i++ ))
do
for (( j=1; j <= i; j++ ))
do
let "temp = i * j"
echo -n "$i*$j=$temp "
done
echo "" #output newline
done
#!/bin/bash
i=0
until [[ "$i" -gt 5 ]] #大於5
do
let "square=i*i"
echo "$i * $i = $square"
let "i++"
done
跳出語句(break,continue)
break: 在for、while和until迴圈中break可強行退出迴圈,break語句僅能退出當前的迴圈,如果是兩層迴圈巢狀,則需要在外層迴圈中使用break.
#!/bin/bash
sum=0
for (( i=1; i <= 100; i++))
do
let "sum+=i"
if [ "$sum" -gt 1000 ]
then
echo "1+2+...+$i=$sum"
break
fi
done
continue: 在for、while和until中用於讓指令碼跳過其後面的語句,執行下一次迴圈.continue用於顯示100內能被7整除的數.
#!/bin/bash
m=1
for (( i=1; i < 100; i++ ))
do
let "temp1=i%7" #被7整除
if [ "$temp1" -ne 0 ]
then
continue
fi
echo -n "$i "
let "temp2=m%7" #7個數字換一行
if [ "$temp2" -eq 0 ]
then
echo ""
fi
let "m++"
done
SELECT 語句
select結構從技術角度看不能算是迴圈結構,只是相似而已,它是bash的擴充套件結構用於互動式選單顯示,功能類似於case結構比case的互動性要好.
[[email protected] ~]# cat select.sh
#!/bin/bash
echo -e "請選擇系統型別?"
select var in "Linux" "GNU HURD" "FreeBSD" "Other";
do
if [ $var == "Linux" ]
then
echo -e "您的系統是Linux"
elif [ $var == "FreeBSD" ]
then
echo -e "您的系統是FreeBSD"
fi
break
done
[[email protected] ~]# bash select.sh
請選擇系統型別?
1) Linux
2) GNU HURD
3) FreeBSD
4) Other
#? 1
您的系統是Linux
#!/bin/bash
declare -a serial
serial=(1 2 3 4)
PS3="Enter a number: "
select var in "a" "b" "c" "d"
do
if ! echo ${serial[@]} | grep -q $REPLY
then
echo "please enter [1-4]."
continue
fi
echo "your anwser is: $var"
break
done
[[email protected] ~]# bash select.sh
1) a
2) b
3) c
4) d
Enter a number: 1
your anwser is: a
FUNCTION 函式
[[email protected]alhost ~]# cat function.sh
#!/bin/bash
function my_print()
{
echo -e "------------------------"
echo -e "hello world"
echo -e "------------------------"
return "127"
}
my_print
echo $?
[[email protected] ~]# bash function.sh
------------------------
hello world
------------------------
127
推薦一個shell部落格:
https://blog.csdn.net/taiyang1987912/article/details/38929069