一、循环语句
1.1 for循环语句
1.1.1 for语句的结构
■读取不同的变量值,用来逐个执行同一组命令
1.1.2 for语句应用示例
示例1:
■批量添加用户
●用户名存在user.txt中,每行一个
●初始密码均设为123456
●验证脚本
[root@localhost ~]# vi /root/user.txt
tom
jack
kitty
[root@localhost ~]# vi uadd.sh
#!/bin/bash
ULIST=$(cat /root/user.txt)
for UNAME in $ULIST
do
useradd $UNAME
echo "123456" | passwd --stdin $UNAME &>/dev/null
done
[root@localhost ~]# chmod +x uadd.sh
[root@localhost ~]# ./uadd.sh
[root@localhost ~]# tail -3 /etc/passwd
tom:x:1001:1001::/home/tom:/bin/bash
jack:x:1002:1002::/home/jack:/bin/bash
kitty:x:1003:1003::/home/kitty:/bin/bash
■若要删除添加的用户,将执行以下命令:
[root@localhost ~]# cp uadd.sh udel.sh
[root@localhost ~]# vi udel.sh
#!/bin/bash
ULIST=$(cat /root/user.txt)
for UNAME in $ULIST
do
userdel -r $UNAME
[ $? = 0 ] && echo "已删除$UNAME"
done
[root@localhost ~]# ./udel.sh
已删除tom
已删除jack
已删除kitty
示例2:
■根据IP地址检查主机状态
●IP地址存放在ipadds.txt文件中,每行一个
●使用ping命令检测各主机的连通性
[root@localhost ~]# vi /root/ipadds.txt
20.0.0.17
192.168.1.100
20.0.0.1
20.0.0.2
[root@localhost ~]# vi chkhosts.sh
#!/bin/bash
HLIST=$(cat /root/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &>/dev/null
if [ $? = 0 ]
then
echo "Host $IP is up" && echo "Host $IP is up" >>/root/ipup.txt
else
echo "Host $IP is down" && echo "Host $IP is down" >>/root/ipdown.txt
fi
done
[root@localhost ~]# chmod +x chkhosts.sh
[root@localhost ~]# ./chkhosts.sh
Host 20.0.0.1 is up
Host 20.0.0.2 is up
Host 20.0.0.17 is down
Host 192.168.1.100 is down
[root@localhost ~]# cat /root/ipup.txt ##查看up记录##
Host 20.0.0.1 is up
Host 20.0.0.2 is up
[root@localhost ~]# cat /root/ipdown.txt ##查看down记录##
Host 20.0.0.17 is down
Host 192.168.1.100 is down
1.2 while循环语句
■重复测试某个条件,只要条件成立则反复执行
示例1:
■批量添加用户
●用户名称以stu开头,按数字顺序进行编号
●一个添加20个账户,即stu1、stu2、…stu20
●初始密码均设为123456
[root@localhost ~]# vi uaddwhile.sh
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
useradd ${PREFIX}$i
echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
let i++
done
[root@localhost ~]# chmod +x uaddwhile.sh
[root@localhost ~]# ./uaddwhile.sh
[root@localhost ~]# tail -20 /etc/passwd
stu1:x:1001:1001::/home/stu1:/bin/bash
stu2:x:1002:1002::/home/stu2:/bin/bash
stu3:x:1003:1003::/home/stu3:/bin/bash
stu4:x:1004:1004::/home/stu4:/bin/bash
stu5:x:1005:1005::/home/stu5:/bin/bash
stu6:x:1006:1006::/home/stu6:/bin/bash
stu7:x:1007:1007::/home/stu7:/bin/bash
stu8:x:1008:1008::/home/stu8:/bin/bash
stu9:x:1009:1009::/home/stu9:/bin/bash
stu10:x:1010:1010::/home/stu10:/bin/bash
stu11:x:1011:1011::/home/stu11:/bin/bash
stu12:x:1012:1012::/home/stu12:/bin/bash
stu13:x:1013:1013::/home/stu13:/bin/bash
stu14:x:1014:1014::/home/stu14:/bin/bash
stu15:x:1015:1015::/home/stu15:/bin/bash
stu16:x:1016:1016::/home/stu16:/bin/bash
stu17:x:1017:1017::/home/stu17:/bin/bash
stu18:x:1018:1018::/home/stu18:/bin/bash
stu19:x:1019:1019::/home/stu19:/bin/bash
stu20:x:1020:1020::/home/stu20:/bin/bash
■若要删除创建的用户,则执行以下命令:
[root@localhost ~]# cp uaddwhile.sh udelwhile.sh
[root@localhost ~]# vi udelwhile.sh
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
userdel -r ${PREFIX}$i
# echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
let i++
done
[root@localhost ~]# chmod +x udelwhile.sh
[root@localhost ~]# ./udelwhile.sh
[root@localhost ~]# tail -2 /etc/passwd
tcpdump:x:72:72::/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin ##成功删除##
示例2:
■猜商品价格游戏
●通过变量RANDOM获得随机数
●提示用户猜测并记录次数,猜中后退出循环
[root@localhost ~]# vi price.sh
#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
TIMES=0
echo "商品实际价格范围为0-999,猜猜看是多少?"
while true
do
read -p "请输入你猜测的价格数目:" INT
let TIMES++
if [ $INT -eq $PRICE ];then
echo "恭喜你答对了,实际价格是$PRICE" echo "您总共猜测了 $TIMES 次"
exit 0
elif [ $INT -gt $PRICE ];then
echo "太高了!"
else
echo "太低了!"
fi
done
[root@localhost ~]# chmod +x price.sh
[root@localhost ~]# ./price.sh
商品实际价格范围为0-999,猜猜看是多少?
请输入你猜测的价格数目:100
太低了!
请输入你猜测的价格数目:555
太低了!
请输入你猜测的价格数目:666
太低了!
请输入你猜测的价格数目:888
太高了!
请输入你猜测的价格数目:777
太低了!
请输入你猜测的价格数目:800
太低了!
请输入你猜测的价格数目:850
太低了!
请输入你猜测的价格数目:880
太高了!
请输入你猜测的价格数目:860
太低了!
请输入你猜测的价格数目:870
太高了!
请输入你猜测的价格数目:865
太低了!
请输入你猜测的价格数目:866
太低了!
请输入你猜测的价格数目:867
太低了!
请输入你猜测的价格数目:868
恭喜你答对了,实际价格是868 echo 您总共猜测了 14 次
1.3 until循环语句
1.3.1 until语句的结构
■重复测试某个条件,只要条件不成立则反复执行
示例1:
■计算1~50的和值
●通过循环累加的方式计算1~50的和值
[root@localhost ~]# vi sum.sh
#!/bin/bash
i=0;s=0
until [ $i -eq 50 ]
do
let "i=$i+1";let "s=$s+$i"
done
echo 'sum(1..50)='$s
[root@localhost ~]# chmod +x sum.sh
[root@localhost ~]# ./sum.sh
sum(1..50)=1275
■或者可以做以下操作,意义一样
[root@localhost ~]# vi sum.sh
let i++
#!/bin/bash
i=1;s=0
until [ $i -gt 50 ]
do
let "s=$s+$i"
let i++
done
echo 'sum(1..50)='$s
[root@localhost ~]# ./sum.sh
sum(1..50)=1275
二、 Shell函数
2.1 Shell函数
■将命令序列按格式写在一起
■可方便重复使用命令序列
■Shell函数定义
【 function 】 函数名(){
命令序列
【return x】
}
■调用函数的方法
函数名 【函数1】 【函数2】
2.1 函数应用示例
示例1:
■两个数字求和
●通过sum() {}定义函数
●使用read命令交互输入两个数并求和
[root@localhost ~]# vi SUM.sh
#!/bin/bash
#函数求和
sum(){
read -p "请输入第一个数:" NUM1
read -p "请输入第二个数:" NUM2
echo "您输入的两个数为:$NUM1和$NUM2"
SUM=$(( NUM1+NUM2 ))
echo "两个数的和为:$SUM"
}
sum
[root@localhost ~]# chmod +x SUM.sh
[root@localhost ~]# ./SUM.sh
请输入第一个数:10
请输入第二个数:20
您输入的两个数为:10和20
两个数的和为:30
或者可以进行以下操作:
[root@localhost ~]# vi SUM.sh
#!/bin/bash
#函数求和
sum(){
read -p "请输入第一个数:" NUM1
read -p "请输入第二个数:" NUM2
echo "您输入的两个数为:$NUM1和$NUM2"
SUM=$(expr $NUM1 + $NUM2)
echo "两个数的和为:$SUM"
}
sum
[root@localhost ~]# ./SUM.sh
请输入第一个数:5
请输入第二个数:8
您输入的两个数为:5和8
两个数的和为:13
2.2 函数的作用范围
■函数在Shell脚本中仅在当前Shell环境中有效
■Shell脚本中变量默认全局有效
■将变量限定在函数内部使用local命令
■示例
●函数内部变量通过local来实现
◆通过定义myfun函数,在其内部设置局部变量i
◆函数内部和外部分别赋值,进行结果验证
2.3 函数的参数
■参数的用法
函数名称 参数1 参数2 参数3 …
参数的表示方法
$1 $2 … ${10} ${11}
■示例
●通过函数参数将日志信息写入文件
◆通过定义appendfile函数实现
2.4 递归函数
■调用自己本身的函数
■示例
●递归遍历记录
◆通过定义递归函数list_files来实现
[root@localhost ~]# vi fun.sh
#!/bin/bash
function list_files()
{
for f in `ls $1`;
do
if [ -d "$1$f" ];then
echo "$2$f"
list_files "$1$f" " $2"
else
echo "$2$f"
fi
done
}
list_files "/var/log" ""
[root@localhost ~]# chmod +x fun.sh
[root@localhost ~]# ./fun.sh
anaconda
anaconda.log
ifcfg.log
journal.log
ks-script-_jzieq.log
ks-script-VOaRnV.log
packaging.log
program.log
storage.log
syslog
X.log
audit
audit.log
三、 Shell数组
3.1 Shell数组
■应用场景包括
●获取数组长度
●获取元素长度
●遍历元素
●元素切片
●元素替换
●元素删除
●…
■数组定义方法
●方法1:数组名=(vlaue0 vlaue1 vlaue2 …)
●方法2:数组名=([0]=vlaue [1]=vlaue [2]=vlaue …)
方法3:列表名=“value0 value1 value2 …”
数组名=($列表名)
●方法4:数组名[0]=“value”
数组名[1]=“value”
数组名[2]=“value”
…
■数组包括的数据类型
●数值类型
●字符类型
◆使用""或’'定义
示例:
■获取数组长度
[root@localhost ~]# arr_number=(1 2 3 4 5)
[root@localhost ~]# arr_length=${#arr_number[*]}
[root@localhost ~]# echo $arr_length
5
[root@localhost ~]# arr_length_1=${#arr_number[@]}
[root@localhost ~]# echo $arr_length_1
5
■读取某下标赋值
[root@localhost ~]# arr_index2=${arr_number[2]}
[root@localhost ~]# echo $arr_index2
3
■数组遍历
[root@localhost ~]# vi array_traverse.sh
#!/bin/bash
arr_number=(1 2 3 4 5)
for v in ${arr_number[@]}
do
echo $v
done
[root@localhost ~]# chmod +x array_traverse.sh
[root@localhost ~]# ./array_traverse.sh
1
2
3
4
5
■数组切片
[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# echo ${arr[@]} ##输出整个数组##
1 2 3 4 5
[root@localhost ~]# echo ${arr[@]:0:2} ##${数组名[@或*]:起始位置:长度}
1 2
[root@localhost ~]# echo ${arr[@]:2:3}
3 4 5
■数组替换
[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# echo ${arr[@]/4/66} ##${数组名[@或*]/查找字符/替换字符}##
1 2 3 66 5
[root@localhost ~]# echo ${arr[@]} ##不会替换数组原有字符##
1 2 3 4 5
[root@localhost ~]# arr=(${arr[@]/4/66}) ##要实现改变原有数组,可通过重新赋值实现#
[root@localhost ~]# echo ${arr[@]}
1 2 3 66 5
■数组删除
[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# unset arr ##删除数组##
[root@localhost ~]# echo ${arr[*]}
[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# unset arr[2] ##删除第三个元素##
[root@localhost ~]# echo ${arr[*]}
1 2 4 5
3.2 Shell脚本测试
■-n:不会执行该脚本,仅查询本语法是否有问题,如果没有语法问题就不显示任何内容,如果有问题会提示报错。
■-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示。
■-x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。