在shell腳本編程中,我們可以根據命令的狀態結果,判斷要不要執行下一步,但是有時候要判斷的問題不止一個,甚至對問題本身都要做判斷;同時問題的結果有時也不止一個,這時要借助簡單的邏輯與和邏輯或,就顯得很無力;要完成復雜的任務,需要借助一定的流程控制:順序執行、選擇執行、循環執行、同時在腳本執行過程中,有用戶交互輸入的需;
if語句
case語句
for語句
while語法
until語句
continue語句
break語句
-
if語法
(1)單分支if語句結構
if expression;then
statement1
statement2
...
fi
expression:表達式可以是整數、字符、文件比較判斷、命令;expression的結果為true時,才執行then后面的statement,
注意:
(1)expression中使用[ ]、[[ ]]時記得方括號兩邊要有空格,如何then不想換行寫,需要expression后面有“;”結尾,否則語法錯誤;
(2)語句最后要有結尾fi,否則語法錯誤;
舉例:測試用戶,存在就問候
[root@xia7 ~]# id xia
uid=1011(xia) gid=1011(xia) groups=1011(xia)
[root@xia7 ~]#
[root@xia7 ~]# if id xia &>/dev/null;then echo "hell tom";fi
hell tom
[root@xia7 ~]#
root@xia7 ~]# id tom
id: tom: no such user
[root@xia7 ~]#
[root@xia7 ~]# if id tom &>/dev/null;then echo "hell tom";fi
[root@xia7 ~]#
(2)雙分支if語句結構
if expression;then
statement1
statement2
...
else
statement1
statement2
...
fi
expression:表達式為true時,執行then后面的statement,表達式為false時,執行else后面的statement;
舉例:測試用戶存在就問候,否則就添加用戶
[root@xia7 ~]# id tom
id: tom: no such user
[root@xia7 ~]# if id tom &>/dev/null;then echo "hell tom";else useradd tom &>/dev/null;echo "tom is add finished";fi
tom is add finished
[root@xia7 ~]#
[root@xia7 ~]# id xia
uid=1011(xia) gid=1011(xia) groups=1011(xia)
[root@xia7 ~]#
[root@xia7 ~]# if id xia &>/dev/null;then echo "hell xia";else useradd tom &>/dev/null;echo "xia is add finished";fi
hell xia
[root@xia7 ~]#
(3)多分支if語句結構
if expression1;then
statement1
...
elif expression2;then
statement1
...
else
statement1
...
fi
上面的語法中有多個判斷條件expression,執行選擇順序是從上往下,只要前面有一個expression的結果為true時,就執行相應后面then的statement,然后退出if語句,如果前面的expression都為false時,就執行else后面的statement;
注意:
1.如果后面的expression也為true是,不會執行,只會判斷第一結果為true時,執行后面then的statement;
舉例:測試年齡段
#!/bin/bash
#
read -p "please input:" age
if [ $age -le 12 ];then
echo "is a child"
elif [ $age -le 16 ];then
echo " is a young"
elif [ $age -eq 18 ];then
echo "is barely of age"
elif [ $age -lt 120 ];then
echo "
2.case語句
當有多個判斷條件為字符時,在用if語句就顯得比較繁瑣,結構看起來也不是很清晰,這時使用case語句結構就顯得相對比較清晰簡明;
case語句結構
case varname in
模式1)
statement
...
;;
模式2)
statement
...
;;
*)
statement
...
;;
esac
varname為變量名,可以自定義;其值為后面模式定義到的字符;控制流程:in:為關鍵字,當varname的值為模式1,就執行其后的statement,“;;”兩個分號表示執行后退出case語句;跟多分支if語句一樣, 一旦匹配到,不會再判斷后面;*)表示前面的都匹配不到,就執行這條默認的模式下的statement;
注意esac結尾;
模式:可以使用global風格的通配符:
*:表示任意長度的任意字符
[]表示指定范圍內的任意單個字符
| :表示或者的關系
舉例:測試文件類型
#!/bin/bash
#
read -p "please input file name:" file
[[ -z $file ]] && echo "you have not input" && exit 1
[ -e $file ] && echo "you input file not exist" && exit 1
type=`ls -l $file |cut -c 1`
case $type in
l|p|s)
echo "$file is special file"
;;
b|c)
echo "$file is device file"
;;
-)
echo "$file is flat file"
;;
d)
echo "$file is dir file"
;;
*)
echo "$file is other file"
;;
esac
3.for循環語句結構
for varname in list;do
循環體
done
for:為keyword varname:為變量名,可以自定義,list為列表值,有多個,do固定格式;done:為結束符;
流程控制:當執行for時會把list列表中的值取出來賦值給varname變量,執行循環體,執行完循環體后再到列表中取值賦值給變量,直到把列表中的值取完賦值給變量,才結束循環;
in 列表生成方式:
1.直接給出列表,例如:tom jerry xiaoming 注意多個值之間用空格分割,甚至特殊字符需要用""或者/轉義符 ;
2.整數列表:
{stat..end}
`seq start [step] end`
$(seq [start [step] end)
3.能夠返回列表的命令
$(command):比如ls
`command`
4.使用glob風格的通配符
*.sh
5.使用特殊變量引用
$@
$*
$1 $1 …
for循環進入條件:列表中有值
for循環退出的條件:遍歷完列表中的值
舉例:創建100個空文件
#!/bin/bash
#
for I in {1..100};do
touch file$I &>/dev/null
echo "create file$I finished"
done
[root@xia7 ~]# for I in {1..100};do touch file$I &>/dev/null;echo "create file$I finished";done
create file1 finished
create file2 finished
...
create file99 finished
create file100 finished
[root@xia7 ~]#
4.while循環語句結構
while condition;do
循環體
done
while:為keyword condition:為條件表達式,do為固定格式,done為結束;
流程控制:進入循環體之前,先做一次判斷,每次執行循環體之前都會做一次判斷,condition為true時執行循環體,為false時退出循環
while循環進入條件:condition為true時
while循環退出條件: condition為false時
舉例:測試100以內的正整數和
vim f1.sh
#!/bin/bash
#
declare -i I=1
declare -i sum=0
while [ $I -le 100 ];do
sum=$[$sum+$I]
let I++
done
echo "100sum=$sum"
[root@xia7 ~]# chmod +x f1.sh
[root@xia7 ~]# ./f1.sh
100sum=5050
[root@xia7 ~]#
5.until循環語句結構
until condition;do
循環體
done
until:為keyword condition:為條件表達式 do:為固定格式,done:為結束
流程控制:跟while執行的條件表達式相反,每次進入循環體之前判斷condition為false時執行,condition判斷為true時退出循環
until循環進入條件:condition為false時
until循環退出條件:condition為true時
舉例:猜10以內的隨機數字
vim f2.sh
#!/bin/bash
#
r=$[$RANDOM%10+1]
read -p "Please input a number:" num
[[ -z $num ]] && echo "you have not input" && exit 1
until [ $num -eq $r ];do
if [ $num -gt $r ];then
echo "you guess too big"
else
echo "you guess too small"
fi
read -p "please continue to guess:" num
done
echo "Good you guess right !!!"
[root@xia7 ~]# chmod +x f2.sh
[root@xia7 ~]# ./f2.sh
Please input a number:5
you guess too big
please continue to guess:4
you guess too big
please continue to guess:3
Good you guess right !!!
[root@xia7 ~]#
6.循環控制語句
(1)continue語法結構
while condition;do
statement1
...
if expression;then
continue
fi
statement
...
done
continue用于循環體中,出現在哪一層的判斷中,提前結束當前迭代的循環,進入下一輪判斷;
continue [num]:[num]表示層數 指定退出的循環層次,最內層為第一層;
舉例:求100以內偶數之和
#!/bin/bash
#
declare -i ousum=0
declare -i i=0
while [ $i -le 100 ];do
let i++
if [ $[$i%2] -eq 1 ] ;then
continue
fi
let ousum+=$i
done
echo "100 oushu sum is:$ousum"
[root@xia7 ~]# chmod +x f3.sh
[root@xia7 ~]# ./f3.sh
100 oushu sum is:2550
[root@xia7 ~]#
[root@xia7 ~]# bash -x f3.sh
+ declare -i ousum=0
+ declare -i i=0
+ '[' 0 -le 100 ']'
+ let i++
+ '[' 1 -eq 1 ']'
+ continue
+ '[' 1 -le 100 ']'
+ let i++
+ '[' 0 -eq 1 ']'
+ let ousum+=2
+ '[' 2 -le 100 ']'
+ let i++
+ '[' 1 -eq 1 ']'
+ continue
+ '[' 3 -le 100 ']'
(2)break
while condition;do
statement1
...
if expression;then
break
fi
statement
...
done
break:用于循環體中,提前結束當前整個循環退出,最內層為第一層;
可以在死循環中用break,滿足條件執行break,
舉例:向100以內的用戶問好
#!/bin/bash
#
declare -i sum=0
declare -i i=1
while true;do
echo "hello user$i"
if [ $i -ge 100 ];then
break
fi
let i++
done
[root@xia6 ~]# bash -x f4.sh
...
hello user99
+ '[' 99 -ge 100 ']'
+ let i++
+ true
+ echo 'hello user100'
hello user100
+ '[' 100 -ge 100 ']'
+ break
[root@xia6 ~]#
總結:
1.對于選擇執行的語句case,只能對表達式為字符型風格的才能使用,if和case語句在執行時匹配到執行完就退出,不會再看下一條的結果是什么;
2.對于循環語句while和until語句,要把握循環的進入和退出條件,否則造成死循環,無意義的消耗系統資源,對系統負載有影響;
3.對于控制語句continue語句是結束本次迭代循環,進入下一輪判斷,而break是結束退出當前整個循環;
原創文章,作者:xiashixiang,如若轉載,請注明出處:http://www.www58058.com/38242
態度不夠端正,發布前未進行預覽,發布后代碼都混在一起了。