在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.178linux.com/38242