一、循环语句

1、for循环详解

for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理。当要处理的数据有范围时,
使用for循环语句就再适合不过了。

读取不同的变量值,用来逐个执行同一组命令

语法:
for 变量名 in 取值列表
do
命令序列(命令行)
done

示例1:

下面使用for循环语句从列表文件中读取多个用户,然后为其逐一创建用户账户并设置密码。
首先创建用户名称的列表文件users.txt,每个用户名称单独一行。

1
2
3
4
5
6
[root@node1 ~]# vim user.txt
marry
tom
rose
mike

接下来编写shell标本addusers.sh。在脚本中使用read命令读取用户输入的密码值,然后赋值给PASSWD
变量,并通过-p参数向用户显示一段提示信息,告诉用户正在输入的内容即将作为账户密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@node1 ~]# vim userpasswd.sh
#!/bin/bash
read -p "enter the user password:" PASSWD
for UNAME in `cat /root/user.txt`
do
useradd $UNAME
echo "$PASSWD" | passwd --stdin $UNAME
echo "$UNAME",create success
done

[root@node1 ~]# chmod +x userpasswd.sh
[root@node1 ~]# ./userpasswd.sh
enter the user password:redhat
Changing password for user marry.
passwd: all authentication tokens updated successfully.
marry,create success
Changing password for user tom.
passwd: all authentication tokens updated successfully.
tom,create success
Changing password for user rose.
passwd: all authentication tokens updated successfully.
rose,create success
Changing password for user mike.
passwd: all authentication tokens updated successfully.
mike,create success

示例2:

循环输出1-10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@node1 ~]# vim qq.sh
#!/bin/bash
for ((i=1;i<=10;i++))
do
echo $i
done

[root@node1 ~]# chmod +x qq.sh
[root@node1 ~]# ./qq.sh
1
2
3
4
5
6
7
8
9
10

示例3:

用for语句,输出1-100的所有整数和

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@node1 ~]# vim ee.sh
#!/bin/bash
a=0
for ((i=1;i<=100;i++))
do
a=$(($a+$i))
done
echo "1-100所有整数相加的和未$a"

[root@node1 ~]# chmod +x ee.sh
[root@node1 ~]# ./ee.sh
1-100所有整数相加的和未5050

示例4:

根据IP地址检测主机状态
主机列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@node1 ~]# vim iplist
192.168.100.112
192.168.100.114
192.168.100.115

[root@node1 ~]# vim rr.sh
#!/bin/bash
ip=$(cat /root/iplist)
for i in $ip
do
ping -c 3 $i &>/dev/null
if [ $? -eq 0 ];then
echo "$i通"
else
echo "$i不通"
fi
done

[root@node1 ~]# chmod +x rr.sh
[root@node1 ~]# ./rr.sh
192.168.100.112
192.168.100.114
192.168.100.115不通

2、while语句

重复测试某个条件,只要条件成立,则反复执行

示例1:

显示0-10的所有整数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@node1 ~]# vim yy.sh
#!/bin/bash
a=0
while [ $a -le 10 ]
do
echo $a
let a++
done

[root@node1 ~]# chmod +x yy.sh
[root@node1 ~]# ./yy.sh
0
1
2
3
4
5
6
7
8
9
10

示例2:

求1-100的整数和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@node1 ~]# vim uu.sh
#!/bin/bash
i=0
n=1
while [ $n -le 100 ]
do
i=$(( $i + $n ))
let n++
done
echo "1-100的和为:$i"

[root@node1 ~]# chmod +x uu.sh
[root@node1 ~]# ./uu.sh
1-100的和为:5050

随机数

1
2
3
4
5
6
7
8
9
[root@node1 ~]# expr 5 % 10
5
[root@node1 ~]# expr $RANDOM % 50
36
[root@node1 ~]# expr $RANDOM % 50
47
[root@node1 ~]# expr $RANDOM % 50
22

示例3:

随机猜数字游戏,1000以内的猜数字游戏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@node1 ~]# vim ii.sh
#!/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

[root@node1 ~]# chmod +x ii.sh
[root@node1 ~]# ./ii.sh
数字范围为0-999的整数,猜猜看
请输入你猜的整数:500
你猜高了
请输入你猜的整数:250
你猜低了
请输入你猜的整数:350
你猜高了
请输入你猜的整数:300
你猜低了
请输入你猜的整数:325
你猜高了
请输入你猜的整数:310
你猜低了
请输入你猜的整数:317
你猜低了
请输入你猜的整数:322
你猜高了
请输入你猜的整数:320
恭喜你答对了,数字为320
你总共猜了9

3、until语句

重复测试某个条件,只要条件不成立,则反复执行

示例1:

求1-100的整数和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@node1 ~]# vim aa.sh
#!/bin/bash
a=0
for i in {1..100}
do
a=$((a + i))
done
echo "1-100的整数和为: $a"

[root@node1 ~]# chmod +x aa.sh
[root@node1 ~]# ./aa.sh
1-100的整数和为: 5050


4、双for循环

即在一个for循环内部再加一个for循环

1
2
3
4
5
6
7
8
9
#!/bin/bash
for ((a=1;a<=5;a++))
do
echo "a=$a"
for ((b=1;b<=5;b++))
do
echo "b=$b"
done
done

示例:九九乘法表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@node1 ~]# vim a.sh
#!/bin/bash
for (( a=1;a<10;a++ ))
do
for (( b=1;b<=a;b++ ))
do
echo -en "$b*$a=$(($a*$b))\t"
done
echo
done


[root@node1 ~]# chmod +x a.sh
[root@node1 ~]# ./a.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

5、break和continue

在内循环执行break 就跳出当前的内循环了,去执行外循环了
作用:
1跳出当前循环
2并且break下面的语句不去执行

(1)break,我们可以通过内外循环的输出来看break的特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@node1 ~]# vim b.sh
#!/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@node1 ~]# chmod +x b.sh
[root@node1 ~]# ./b.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就不去判断了

(2)continue

中止某次循环,不会完全终止整个命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@node1 ~]# vim c.sh
#!/bin/bash
#continue
for (( a=1;a<=15;a++))
do
if [ $a -gt 5 ] && [ $a -lt 10 ]
then
continue
fi
echo " $a "
done

[root@node1 ~]# chmod +x c.sh
[root@node1 ~]# ./c.sh
1
2
3
4
5
10
11
12
13
14
15

二、函数

将命令序列按格式写在一起
可重复使用命令序列

1、shell函数定义格式

1
2
3
4
5
6
7
8
9
10
11
12
13
function 函数名{ 

命令序列

}


函数名(){

命令序列

}

2、函数返回值

return
return 表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值(0-255)
原则:
1.函数已结束就取返回值,因为 $? 只是对最后一条命令进行判断
2.0-255,超出时 除以256取余
echo也能直接返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@node1 ~]# vim a.sh
#!/bin/bash
#测试
function sq {
read -p "请输入任意一个整数值:" n
return $[$n*2]
}

sq
echo "$?"
[root@node1 ~]# chmod +x a.sh
[root@node1 ~]# ./a.sh
请输入任意一个整数值:20
40
[root@node1 ~]# ./a.sh
请输入任意一个整数值:30
60

3、函数传参

函数变量的作用范围(局部变量以及全局变量)
函数在shell脚本中仅在当前shell环境中有效
shell脚本中变量默认全局有效
将变量限定一个函数的内部local,即局部变量

(1)传参

1
2
3
4
5
6
7
8
9
10
11
[root@node1 ~]# vim aa.sh
#!/bin/bash
sum1 () {
sum=$[ $1 + $2 ]
echo $sum
}
sum1 $1 $2
[root@node1 ~]# chmod +x aa.sh
[root@node1 ~]# ./aa.sh 20 30
50

(2)变量的局部与全局

将变量限定在函数内部使用local命令
即这个local的变量仅仅在当前的函数内有效,在别的函数中无效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
abc () {
echo "函数内的未经过local的变量i值$i"
local i
i=6
echo "函数内的变量i值是$i"
}
i=9
abc
echo "函数外面的变量i值是$i"

[root@node1 ~]# ./cc.sh
函数内的未经过local的变量i值9
函数内的变量i值是6
函数外面的变量i值是9

(3)local的进击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
abc () {
echo "inside1 $i"
let i++
local i
i=8
echo "inside2 $i"
}
i=9
abc
echo "outside $i"

[root@node1 ~]# ./cc.sh
inside1 9
inside2 8
outside 10

4、递归(调用自己)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
function cy() {
if [ $1 -eq 1 ];then
echo 1
else
local temp=$[ $1 - 1 ]
local result=`cy $temp`
echo $[ result * $1 ]
fi
}
read -p "输入一个值:" vaule
result=`cy $vaule`
echo "阶乘的值为: $result"

[root@node1 ~]# ./dd.sh
输入一个值:5
阶乘的值为: 120
[root@node1 ~]# ./dd.sh
输入一个值:3
阶乘的值为: 6

5、函数库

就是把一般脚本的主体执行代码和定义函数部分相互分离,把定义的函数部分集中放在同一个脚本中。
具体执行的时候,只需要直接进行调用函数集合的脚本文件即可。

这里我把加减乘除共4个函数,做了一个函数库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[root@node1 ~]# 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@node1 ~]# 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@node1 ~]# chmod +x ff.sh
[root@node1 ~]# ./ff.sh
请输入第一个数字:5
请输入第二个数字:2
两数之和为: 7
两数之差为: 3
两数之积为: 10
两数之商为: 2