前言:
在linux shell中,通常我们将一些命令写在一个文件中就算是一个shell脚本了,但是如果需要执行更为复杂的逻辑判断,我们就需要使用流程控制语句来支持了。
所谓流程控制既是通过使用流程控制语句对程序流程的选择、循环、转向和返回等进行控制。流程控制是所有编程语言分重要组成部分,linux shell同样有一套自己的流程控制语句,其中主要包括条件语句(if),循环语句(for,while),选择语句(case)。本文将会对这几种语句进行介绍同时引用示例便于大家理解。文章也会涉及到循环控制语句的介绍,以及while循环的一些常用的特殊用法,快来一起学习吧!
一、条件选择if语句
单分支
if 判断条件;then
条件为真的分支代码
fi
双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支
if 判断条件1; then
条件为真的分支代码
elif 判断条件2; then
条件为真的分支代码
elif 判断条件3; then
条件为真的分支代码
else
以上条件都为假的分支代码
fi
逐条件进行判断,第一次遇为“真”条件时,执行其分支, 而后结束整个if语句
二、条件判断case语句:
case 变量引用 in #变量的引用加$
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
练习:编写脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息
[root@CentOS6 bin]#vim iduser.sh
1 #!/bin/bash
2 #---------------+--------------------------------------+
3 # ☆ Author : huxiaoqi
4 # ☆ Email : 345304057@qq.com
5 # ☆ Blog : http://www.cnblogs.com/qige2017/
6 # ☆ Tel : 13598859921
7 # ☆ Create time : 2017-08-28
8 # ☆ Filename : iduser.sh
9 # ☆ Version : 1.2.1
10 #---------------+--------------------------------------+
11 read -p "Please input the user name: " username #交互式输入用户名,复制给username
12 if id $username &>/dev/null ;then #条件判断用户输入的用户名是否存在
13 echo "$username is exist" #用户名已存在满足条件,打印exist
14 else
15 echo "user$username is cresting.."
16 sleep 1
17 useradd $username &> /dev/null #用户名不存在就创建用户
18 finger $username #查看用户相关信息
19 fi
三、for循环:
for 变量名 in 列表;do
循环体
done
[root@CentOS7 ~]#for id in {10..1..2};do echo The number is $id ;done
The number is 10 #列表也可以`seq 2 2 10`
The number is 8 #同样表示2到10步进2
The number is 6 #因为是命令所以用反引号引起来
The number is 4
The number is 2
执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执 行一次循环体; 直到列表中的元素耗尽,循环结束
列表生成方式:
- 直接给出列表
- 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end) - 返回列表的命令
$(COMMAND) - 使用glob,如:*.sh
- 变量引用; $@, $*
练习:用for实现
1、添加10个用户user1-user10,密码为8位随机字符
[root@CentOS6 bin]#vim useradd10.sh
#!/bin/bash
> /root/user.log #创建并每次清空密码记录文件
for i in {1..10};do #1-10 循环10次
if id user$i &> /dev/null ;then #判断用户是否存在
echo user$i is exist
exit 1 #若存在则退出脚本,有漏洞可以用后边的知识跳过本次循环
fi
useradd user$i &> /dev/null && echo user$i is created
passwd=`cat /dev/urandom | tr -dc 'a-cA-Z0-9' |head -c 8`
#取/dev/urandom文件中的随机字符,tr -dc 'a-cA-Z0-9' |head -c 8 过滤删 除除了大小写字母以及数字的字符,并取前八个(cat /dev/urandom每次生成的随机 数都不一样)。并且赋值passwd变量。
echo $passwd | passwd --stdin user$i &> /dev/dull
passwd -e user$i &> /dev/null
#将用户的密码修改为$passwd,并设置强制登录修改密码
echo user$i:$passwd >> /root/user.log
#将用户名和对应的用户密码重定向到/root/user.log中
done
[root@CentOS6 ~]#cat user.log
user1:THUU66I0
批量创建用户
[root@CentOS6 ~]#echo user{1..10} |xargs -n1 useradd
批量删除用户
[root@CentOS6 ~]#echo user{1..10} |xargs -n1 userdel -r
2、计算100以内所有能被3整除的整数之和
步进思路:
[root@CentOS6 bin]#vim be3.sh
#!/bin/bash
sum=0 #进入循环之前总合为0
for i in `seq 3 3 100`;do #以3开始步进3到100,既取出所有3-100被三整除的数
sum=$[i+sum] #进入循环以后,sum自增方括号内是数值运算不用加空格
其他写法:let sum+=i 或者sum=$((i+$sum)) 小括号方括号内均为数值运算$可以省略
done
echo $sum
取模思路:
sum1=0
for ii in `seq 1 100`;do
if [ $((ii%3)) -eq 0 ];then #若返回值为0则继续执行任务
#计算机只支持整数运算,若ii的值不能被3整除则返回值为假,既不等于0
sum1=$[ii+sum1]
fi
done
echo sum1 is: $sum1
tr思路:
echo {3..100..3}|tr ' ' +|bc
seq思路:
seq -s + 3 3 100 |bc #-s:指定分隔符为+号
3、打印九九乘法表
for l in `seq 9`;do #l:行数循环9次
for q in `seq $l`;do #q列数嵌套循环,每行的列数=当前行数
p=$[q*l] #p为乘积
echo -n "$q*$l=$p " #内层循环,也就是每一行内的循环echo不换行
done
echo #外层循环要换行
done
[root@CentOS6 bin]#99.sh
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
4、打印等腰三角形
[root@CentOS6 bin]#vim triangle.sh
#!/bin/bash
read -p "please input the storey of the triangle: " n
for l in `seq $n` ; do #命令的引用可以用反引号或者$()
for s in `seq $((n-l))`; do #空格数=总行数减当前行数,bash中的算术运算:var=$((算术表达式))或者 var=$[算术表达式]
echo -n " "
done
for t in `seq $((2*l-1))`;do #星数=当前行数*2-1
echo -n "*"
done
echo #每次最外层循环后换行
done
[root@CentOS6 bin]#triangle.sh
please input the storey of the triangle: 5
*
***
*****
*******
*********
四、while循环
用法展示:
while CONDITION; do
循环体
done
CONDITION:循环控制条件;进入循环之前,先做一次判 断;每一次循环之后会再次做判断;条件为“true”,则执行 一次循环;直到条件测试状态为“false”终止循环 。
因此:CONDTION一般应该有循环控制变量;而此变量的值 会在循环体不断地被修正。
进入条件:CONDITION为true
退出条件:CONDITION为false
练习:用while循环实现
1、编写脚本,提示请输入网络地址,如192.168.0.0,判断 输入的网段中主机在线状态,并统计在线和离线主机各多少
[root@CentOS6 bin]#vim whileip.sh
#!/bin/bash
read -p "please input the ip(eg:172.18.0.1): " ip
network=`echo $ip |cut -d "." -f1-3` #C类地址前三位为网络id
i=1 #ip一般从1开始
up=0
down=0
while [ $i -le 254 ];do #255作为网段内的广播ip,所以取1-254之内的循环
if ping -c1 -w1 $network.$i > /dev/null;then #ping一次一秒
echo $network.$i is up!
let up++ #统计开机主机数
else
echo $network.$i is down!
let down++ #统计关机主机数
fi
let i++
done
2、编写脚本,实现打印国际象棋棋盘
思路:
- 棋盘分八行八列,外层循环八次表示行数,内层循环八次表示列数
- 打印空格加底色实现棋盘效果
- 总结规律发现当当前行数与当前列数相加为偶数时打印黄色,当当前行数与当前列数相加为奇数时打印红色
[root@CentOS6 bin]#vim chess.sh
#!/bin/bash
i=1 #初始行数为1进入循环
while [ $i -le 8 ];do #行数小于等于8则继续任务
j=1 #初始列数为1进入内层循环
while [ $j -le 8 ];do #列数小于等于8册继续任务
flag=$[$[i+j]%2] #标记当前行数当前列数和的奇偶性
if [ $flag -eq 0 ];then #当$flag为偶数打印黄色
echo -n -e "