for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理。当要处理的数据有范围时,
使用for循环语句就再适合不过了。
读取不同的变量值,用来逐个执行同一组命令
语法:
for 变量名 in 取值列表
do
命令序列(命令行)
done
示例1:
下面使用for循环语句从列表文件中读取多个用户,然后为其逐一创建用户账户并设置密码。
首先创建用户名称的列表文件users.txt,每个用户名称单独一行。
vim /root/users.txt
jim
bob
marry
rose
mike
接下来编写shell标本addusers.sh。在脚本中使用read命令读取用户输入的密码值,然后赋值给PASSWD
变量,并通过-p参数向用户显示一段提示信息,告诉用户正在输入的内容即将作为账户密码。
vim /root/addusers.sh
#!/bin/bash
read -p "enter the user password:" PASSWD
for UNAME in `cat /root/users.txt`
do
useradd $UNAME
echo "$PASSWD" | passwd --stdin $UNAME
echo "$UNAME",create success
done
示例2:
循环输出1-10
#!/bin/bash
for ((i=1;i<=10;i++)) //自增1
do
echo $i
done
for ((i=1;i<=10;i+=2)) //自增2
示例3:
用for语句,输出1-100的所有整数和
#!/bin/bash
a=0 //先定义一个和的变量
for ((i=1;i<=100;i++))
do
a=$(($a+$i)) //循环赋值(1+..+100)的和给a
done
echo "1-100所有整数相加的和未$a"
示例4:
根据IP地址检测主机状态
主机列表
vim /root/iplist
192.168.100.10
192.168.100.20
192.168.100.30
vim b.sh
#!/bin/bash
ip=$(cat /root/iplist.txt)
for i in $ip
do
ping -c 3 $i &>/dev/null
if [ $? -eq 0 ];then
echo "$i通"
else
echo "$i不通"
fi
done
重复测试某个条件,只要条件成立,则反复执行
示例1:
显示0-10的所有整数
#!/bin/bash
a=0
while [ $a -le 10 ]
do
echo $a
let a++
done
示例2:
求1-100的整数和
#!/bin/bash
i=0
n=1
while [ $n -le 100 ]
do
i=$(( $i + $n ))
let n++
done
echo "1-100的和为:$i"
随机数
[root@rhel8 ~]# expr 555 % 1000
555
[root@rhel8 ~]# expr $RANDOM % 100
42
[root@rhel8 ~]# expr $RANDOM % 100
9
[root@rhel8 ~]# expr $RANDOM % 100
53
[root@rhel8 ~]# expr $RANDOM % 1000
985
[root@rhel8 ~]# expr $RANDOM % 1000
639
示例3:
随机猜数字游戏,1000以内的猜数字游戏
#!/bin/bash
num=$(expr $RANDOM % 1000)
a=0
echo "数字范围为0-999的整数,猜猜看"
while true
do
read -p "请输入你猜的整数:" n
let a++
if [ $n -eq $num ];then
echo "恭喜你答对了,数字为$num"
echo "你总共猜了$a次"
exit 0
elif [ $n -gt $num ];then
echo "你猜高了"
else
echo "你猜低了"
fi
done
重复测试某个条件,只要条件不成立,则反复执行
示例1:
练习
求1-100的整数和
即在一个for循环内部再加一个for循环
#!/bin/bash
for ((a=1;a<=5;a++))
do
echo "a=$a"
for ((b=1;b<=5;b++))
do
echo "b=$b"
done
done
在内循环执行break 就跳出当前的内循环了,去执行外循环了
作用:
1跳出当前循环
2并且break下面的语句不去执行
#!/bin/bash
#break
for(( a=1;a<=5; a++ ))
do
echo "outside $a"
for ((b=1;b<=5;b++ ))
do
if [ $b -eq 4 ]
then
break #这里当b=4的时候,进行break,不进行后面的输出$b.
fi
echo "inside $b "
done
done
[root@rhel8 ~]# ./d.sh
outside 1
inside 1
inside 2
inside 3
outside 2
inside 1
inside 2
inside 3
outside 3
inside 1
inside 2
inside 3
outside 4
inside 1
inside 2
inside 3
outside 5
inside 1
inside 2
inside 3
内循环到4就停止了,5就不去判断了
中止某次循环,不会完全终止整个命令
#!/bin/bash
#continue
for (( a=1;a<=15;a++))
do
if [ $a -gt 5 ] && [ $a -lt 10 ]
then
continue
fi
echo " $a "
done
[root@rhel8 ~]# ./e.sh
1
2
3
4
5
10
11
12
13
14
15
将命令序列按格式写在一起
可重复使用命令序列
function 函数名{
命令序列
}
函数名(){
命令序列
}
return
return 表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值(0-255)
原则:
1.函数已结束就取返回值,因为 $? 只是对最后一条命令进行判断
2.0-255,超出时 除以256取余
echo也能直接返回
测试案例
#!/bin/bash
#测试
function hehe {
read -p "请输入任意一个整数值:" n
return $[$n*2]
}
hehe
echo "$?"
[root@rhel8 ~]# ./aa.sh
请输入任意一个整数值:40
80
[root@rhel8 ~]# ./aa.sh
请输入任意一个整数值:250
244
[root@rhel8 ~]# ./aa.sh
请输入任意一个整数值:256
0
函数变量的作用范围(局部变量以及全局变量)
函数在shell脚本中仅在当前shell环境中有效
shell脚本中变量默认全局有效
将变量限定一个函数的内部local,即局部变量
(1)传参
[root@rhel8 opt]#vim bb.sh
#!/bin/bash
sum1 () {
sum=$[ $1 + $2 ]
echo $sum
}
sum1 $1 $2
[root@rhel8 ~]# ./bb.sh 20 30
50
[root@rhel8 ~]# ./bb.sh 1 6
7
(2)变量的局部与全局
将变量限定在函数内部使用local命令
即这个local的变量仅仅在当前的函数内有效,在别的函数中无效。
#!/bin/bash
abc () {
echo "函数内的未经过local的变量i值$i"
local i
i=6
echo "函数内的变量i值是$i"
}
i=9
abc
echo "函数外面的变量i值是$i"
[root@rhel8 ~]# ./cc.sh
函数内的未经过local的变量i值9
函数内的变量i值是6
函数外面的变量i值是9
(3)local的进击
#!/bin/bash
abc () {
echo "inside1 $i"
let i++
local i
i=8
echo "inside2 $i"
}
i=9
abc
echo "outside $i"
[root@rhel8 ~]# ./cc.sh
inside1 9
inside2 8
outside 10
#!/bin/bash
function hehe() {
if [ $1 -eq 1 ];then
echo 1
else
local temp=$[ $1 - 1 ]
local result=`cy $temp`
echo $[ result * $1 ]
fi
}
read -p "输入一个值:" vaule
result=`hehe $vaule`
echo "阶乘的值为: $result"
[root@rhel8 ~]# ./dd.sh
输入一个值:5
阶乘的值为: 120
[root@rhel8 ~]# ./dd.sh
输入一个值:3
阶乘的值为: 6
就是把一般脚本的主体执行代码和定义函数部分相互分离,把定义的函数部分集中放在同一个脚本中。
具体执行的时候,只需要直接进行调用函数集合的脚本文件即可。
这里我把加减乘除共4个函数,做了一个函数库。
[root@rhel8 ~]# cat ee.sh
#!/bin/bash
#ee.sh函数库
jia() {
result=$[ $1 + $2 ]
echo "$result"
}
jian() {
result=$[ $1 - $2 ]
echo "$result"
}
cheng() {
result=$[ $1 * $2 ]
echo "$result"
}
chu() {
if [ $2 -ne 0 ];then
result=$[ $1 / $2 ]
echo "$result"
else
echo "除法中分母不能为0"
fi
}
[root@rhel8 ~]# cat ff.sh
#!/bin/bash
. /root/ee.sh
read -p "请输入第一个数字:" n
read -p "请输入第二个数字:" m
result1=`jia $n $m`
result2=`jian $n $m`
result3=`cheng $n $m`
result4=`chu $n $m`
echo "两数之和为: $result1"
echo "两数之差为: $result2"
echo "两数之积为: $result3"
echo "两数之商为: $result4"
[root@rhel8 ~]# chmod +x ff.sh
[root@rhel8 ~]# ./ff.sh
请输入第一个数字:5
请输入第二个数字:2
两数之和为: 7
两数之差为: 3
两数之积为: 10
两数之商为: 2
1、创建脚本xx.sh,使用for循环,输出九九乘法表,提示:echo -n 不要在最后自动换行
第一种方法
[root@sb ~]# vim hehe.sh
#!/bin/bash
n=1
while [ $n -le 9 ]
do
for ((i=1;i<=9;i++))
do
[ $i -le $n ] && echo -n "$n*$i=$(($n*$i)) "
done
let n++
echo ""
done
[root@sb ~]# chmod +x hehe.sh
[root@sb ~]# ./hehe.sh
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
第二种方法
[root@sb ~]# vim hehe.sh
#!/bin/bash
for ((n=1;n<=9;n++))
do
for ((i=1;i<=9;i++))
do
[ $i -le $n ] && echo -n "$n*$i=$(($n*$i)) "
done
echo ""
done
[root@sb ~]# ./hehe.sh
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
2、创建脚本xx.sh,使用until求1-100整数和
[root@sb ~]# vim hehe.sh
#!/bin/bash
i=1
n=0
until [ $i -gt 100 ]
do
n=$(( $i + $n ))
let i++
done
echo "1-100的和为:$n"
[root@sb ~]# ./hehe.sh
1-100的和为:5050
3、写一个脚本,要求如下
(1)设定变量xx的值为/etc/passwd
(2)依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么。结果输出如下:
Hello,root,your UID is 0.
(3)统计当前系统一共有多少个用户
[root@sb ~]# vim hehe.sh
#!/bin/bash
sb="/etc/passwd"
hehe=` wc -l $sb | cut -d" " -f1`
for i in `seq 1 $hehe`
do
user=`head -$i $sb|tail -1 | cut -d: -f1`
userid=`head -$i $sb|tail -1 | cut -d: -f3`
echo "Hello,$user,your UID $userid"
done
echo "用户有: $hehe"
[root@sb ~]# chmod +x hehe.sh
[root@sb ~]# ./hehe.sh
[root@sb ~]# ./hehe.sh
Hello,root,your UID 0
Hello,bin,your UID 1
Hello,daemon,your UID 2
Hello,adm,your UID 3
Hello,lp,your UID 4
Hello,sync,your UID 5
Hello,shutdown,your UID 6
Hello,halt,your UID 7
Hello,mail,your UID 8
Hello,operator,your UID 11
Hello,games,your UID 12
Hello,ftp,your UID 14
Hello,nobody,your UID 65534
Hello,dbus,your UID 81
Hello,systemd-coredump,your UID 999
Hello,systemd-resolve,your UID 193
Hello,tss,your UID 59
Hello,polkitd,your UID 998
Hello,unbound,your UID 997
Hello,geoclue,your UID 996
Hello,rtkit,your UID 172
Hello,pipewire,your UID 995
Hello,pulse,your UID 171
Hello,qemu,your UID 107
Hello,usbmuxd,your UID 113
Hello,gluster,your UID 994
Hello,rpc,your UID 32
Hello,avahi,your UID 70
Hello,chrony,your UID 993
Hello,saslauth,your UID 992
Hello,libstoragemgmt,your UID 991
Hello,dnsmasq,your UID 984
Hello,radvd,your UID 75
Hello,sssd,your UID 983
Hello,cockpit-ws,your UID 982
Hello,cockpit-wsinstance,your UID 981
Hello,colord,your UID 980
Hello,rpcuser,your UID 29
Hello,setroubleshoot,your UID 979
Hello,flatpak,your UID 978
Hello,gdm,your UID 42
Hello,clevis,your UID 977
Hello,gnome-initial-setup,your UID 976
Hello,sshd,your UID 74
Hello,tcpdump,your UID 72
Hello,haha,your UID 1000
Hello,apache,your UID 48
用户有: 47
4、编写一个脚本,使用函数测试主机192.168.40.10-192.168.40.20主机是否在线,函数名称为
name
[root@sb ~]# vim hehe.sh
#!/bin/bash
haha() {
ping -c 1 -w 1 "1 &> /dev/null
}
for i in {10..20}
do
if haha 192.168.40.$i;then
echo "192.168.40.$i通"
else
echo "192.168.40.$i不通"
fi
done
[root@sb ~]# ./hehe.sh
192.168.40.10不通
192.168.40.11不通
192.168.40.12不通
192.168.40.13不通
192.168.40.14不通
192.168.40.15不通
192.168.40.16不通
192.168.40.17不通
192.168.40.18不通
192.168.40.19不通
192.168.40.20不通
[root@sb ~]#