• 20.10 for循环
  • 20.11/20.12 while循环
  • 20.13 break跳出循环
  • 20.14 continue结束本次循环
  • 20.15 exit退出整个脚本
  • 扩展
  • select用法 http://www.apelearn.com/bbs/thread-7950-1-1.html

    20.10 for循环

  • 语法:for 变量名 in 条件; do …; done
  • 案例1
    #!/bin/bash
    sum=0
    for i in `seq 1 100`
    do
    sum=$[$sum+$i]
    echo $i
    done
    echo $sum
  • 案列1
  • 1+2+3..+100的和
  • 来写这个脚本,先把1-100打印出来
    
    [root@aming-01 shell]# vi for1.sh

#!/bin/bash
for i in seq 1 100
do
echo $i
done



:wq
[root@aming-01 shell]# vi for1.sh
[root@aming-01 shell]# sh for1.sh
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
[root@aming-01 shell]#

- 然后再做加法

[root@aming-01 shell]# vi for1.sh

#!/bin/bash
sum=0
for i in seq 1 100
do
sum=$[$sum+$i]
done
echo $sum
~

:wq

[root@aming-01 shell]# vi for1.sh
[root@aming-01 shell]# sh -x for1.sh

  • sum=0
    ++ seq 1 100
  • for i in 'seq 1 100'
  • sum=1
  • for i in 'seq 1 100'
  • sum=3
  • for i in 'seq 1 100'
  • sum=6
  • for i in 'seq 1 100'
  • sum=10
  • for i in 'seq 1 100'
  • sum=15
  • for i in 'seq 1 100'
  • sum=21
  • for i in 'seq 1 100'
  • sum=28
  • for i in 'seq 1 100'
  • sum=36
  • for i in 'seq 1 100'
  • sum=45
  • for i in 'seq 1 100'
  • sum=55
  • for i in 'seq 1 100'
  • sum=66
  • for i in 'seq 1 100'
  • sum=78
  • for i in 'seq 1 100'
  • sum=91
  • for i in 'seq 1 100'
  • sum=105
  • for i in 'seq 1 100'
  • sum=120
  • for i in 'seq 1 100'
  • sum=136
  • for i in 'seq 1 100'
  • sum=153
  • for i in 'seq 1 100'
  • sum=171
  • for i in 'seq 1 100'
  • sum=190
  • for i in 'seq 1 100'
  • sum=210
  • for i in 'seq 1 100'
  • sum=231
  • for i in 'seq 1 100'
  • sum=253
  • for i in 'seq 1 100'
  • sum=276
  • for i in 'seq 1 100'
  • sum=300
  • for i in 'seq 1 100'
  • sum=325
  • for i in 'seq 1 100'
  • sum=351
  • for i in 'seq 1 100'
  • sum=378
  • for i in 'seq 1 100'
  • sum=406
  • for i in 'seq 1 100'
  • sum=435
  • for i in 'seq 1 100'
  • sum=465
  • for i in 'seq 1 100'
  • sum=496
  • for i in 'seq 1 100'
  • sum=528
  • for i in 'seq 1 100'
  • sum=561
  • for i in 'seq 1 100'
  • sum=595
  • for i in 'seq 1 100'
  • sum=630
  • for i in 'seq 1 100'
  • sum=666
  • for i in 'seq 1 100'
  • sum=703
  • for i in 'seq 1 100'
  • sum=741
  • for i in 'seq 1 100'
  • sum=780
  • for i in 'seq 1 100'
  • sum=820
  • for i in 'seq 1 100'
  • sum=861
  • for i in 'seq 1 100'
  • sum=903
  • for i in 'seq 1 100'
  • sum=946
  • for i in 'seq 1 100'
  • sum=990
  • for i in 'seq 1 100'
  • sum=1035
  • for i in 'seq 1 100'
  • sum=1081
  • for i in 'seq 1 100'
  • sum=1128
  • for i in 'seq 1 100'
  • sum=1176
  • for i in 'seq 1 100'
  • sum=1225
  • for i in 'seq 1 100'
  • sum=1275
  • for i in 'seq 1 100'
  • sum=1326
  • for i in 'seq 1 100'
  • sum=1378
  • for i in 'seq 1 100'
  • sum=1431
  • for i in 'seq 1 100'
  • sum=1485
  • for i in 'seq 1 100'
  • sum=1540
  • for i in 'seq 1 100'
  • sum=1596
  • for i in 'seq 1 100'
  • sum=1653
  • for i in 'seq 1 100'
  • sum=1711
  • for i in 'seq 1 100'
  • sum=1770
  • for i in 'seq 1 100'
  • sum=1830
  • for i in 'seq 1 100'
  • sum=1891
  • for i in 'seq 1 100'
  • sum=1953
  • for i in 'seq 1 100'
  • sum=2016
  • for i in 'seq 1 100'
  • sum=2080
  • for i in 'seq 1 100'
  • sum=2145
  • for i in 'seq 1 100'
  • sum=2211
  • for i in 'seq 1 100'
  • sum=2278
  • for i in 'seq 1 100'
  • sum=2346
  • for i in 'seq 1 100'
  • sum=2415
  • for i in 'seq 1 100'
  • sum=2485
  • for i in 'seq 1 100'
  • sum=2556
  • for i in 'seq 1 100'
  • sum=2628
  • for i in 'seq 1 100'
  • sum=2701
  • for i in 'seq 1 100'
  • sum=2775
  • for i in 'seq 1 100'
  • sum=2850
  • for i in 'seq 1 100'
  • sum=2926
  • for i in 'seq 1 100'
  • sum=3003
  • for i in 'seq 1 100'
  • sum=3081
  • for i in 'seq 1 100'
  • sum=3160
  • for i in 'seq 1 100'
  • sum=3240
  • for i in 'seq 1 100'
  • sum=3321
  • for i in 'seq 1 100'
  • sum=3403
  • for i in 'seq 1 100'
  • sum=3486
  • for i in 'seq 1 100'
  • sum=3570
  • for i in 'seq 1 100'
  • sum=3655
  • for i in 'seq 1 100'
  • sum=3741
  • for i in 'seq 1 100'
  • sum=3828
  • for i in 'seq 1 100'
  • sum=3916
  • for i in 'seq 1 100'
  • sum=4005
  • for i in 'seq 1 100'
  • sum=4095
  • for i in 'seq 1 100'
  • sum=4186
  • for i in 'seq 1 100'
  • sum=4278
  • for i in 'seq 1 100'
  • sum=4371
  • for i in 'seq 1 100'
  • sum=4465
  • for i in 'seq 1 100'
  • sum=4560
  • for i in 'seq 1 100'
  • sum=4656
  • for i in 'seq 1 100'
  • sum=4753
  • for i in 'seq 1 100'
  • sum=4851
  • for i in 'seq 1 100'
  • sum=4950
  • for i in 'seq 1 100'
  • sum=5050
  • echo 5050
    5050
    [root@aming-01 shell]#
- 让每次的相加也显示出来

[root@aming-01 shell]# vi for1.sh

#!/bin/bash
sum=0
for i in seq 1 100
do
echo "$sum + $i"
sum=$[$sum+$i]
echo $sum
done
echo $sum
~


:wq
[root@aming-01 shell]# vi for1.sh
[root@aming-01 shell]# sh for1.sh
0 + 1
1
1 + 2
3
3 + 3
6
6 + 4
10
10 + 5
15
15 + 6
21
21 + 7
28
28 + 8
36
36 + 9
45
45 + 10
55
55 + 11
66
66 + 12
78
78 + 13
91
91 + 14
105
105 + 15
120
120 + 16
136
136 + 17
153
153 + 18
171
171 + 19
190
190 + 20
210
210 + 21
231
231 + 22
253
253 + 23
276
276 + 24
300
300 + 25
325
325 + 26
351
351 + 27
378
378 + 28
406
406 + 29
435
435 + 30
465
465 + 31
496
496 + 32
528
528 + 33
561
561 + 34
595
595 + 35
630
630 + 36
666
666 + 37
703
703 + 38
741
741 + 39
780
780 + 40
820
820 + 41
861
861 + 42
903
903 + 43
946
946 + 44
990
990 + 45
1035
1035 + 46
1081
1081 + 47
1128
1128 + 48
1176
1176 + 49
1225
1225 + 50
1275
1275 + 51
1326
1326 + 52
1378
1378 + 53
1431
1431 + 54
1485
1485 + 55
1540
1540 + 56
1596
1596 + 57
1653
1653 + 58
1711
1711 + 59
1770
1770 + 60
1830
1830 + 61
1891
1891 + 62
1953
1953 + 63
2016
2016 + 64
2080
2080 + 65
2145
2145 + 66
2211
2211 + 67
2278
2278 + 68
2346
2346 + 69
2415
2415 + 70
2485
2485 + 71
2556
2556 + 72
2628
2628 + 73
2701
2701 + 74
2775
2775 + 75
2850
2850 + 76
2926
2926 + 77
3003
3003 + 78
3081
3081 + 79
3160
3160 + 80
3240
3240 + 81
3321
3321 + 82
3403
3403 + 83
3486
3486 + 84
3570
3570 + 85
3655
3655 + 86
3741
3741 + 87
3828
3828 + 88
3916
3916 + 89
4005
4005 + 90
4095
4095 + 91
4186
4186 + 92
4278
4278 + 93
4371
4371 + 94
4465
4465 + 95
4560
4560 + 96
4656
4656 + 97
4753
4753 + 98
4851
4851 + 99
4950
4950 + 100
5050
5050
[root@aming-01 shell]#

- 其实大多是还是针对文件做循环
- 文件列表循环

#!/bin/bash
cd /etc/
for a in ls /etc/
do
if [ -d $a ]
then
ls -d $a
fi
done

- 脚本必须进来这个目录才可以使用ls命令

[root@aming-01 shell]# ls /root/shell/
01.sh case.sh file1.sh file2.sh for1.sh if1.sh if2.sh if3.sh if4.sh
[root@aming-01 shell]# cd
[root@aming-01 ~]# ls /root/shell/
01.sh case.sh file1.sh file2.sh for1.sh if1.sh if2.sh if3.sh if4.sh
[root@aming-01 ~]# ls file1.sh
ls: 无法访问file1.sh: 没有那个文件或目录
[root@aming-01 ~]# cd /root/shell/
[root@aming-01 shell]# ls file1.sh
file1.sh
[root@aming-01 shell]#


- 文件列表循环

[root@aming-01 shell]# vim for2.sh

[1]+ 已停止 vim for2.sh

[root@aming-01 shell]# fg
vim for2.sh

#!/bin/bash
cd /etc/
for a in ls /etc/
do
[ -d $a ] && ls $a
if [ -d $a ]
then
echo $a
ls $a
fi
done
~


:wq

- 来执行下,内容太多,省略了大部分

[root@aming-01 shell]# sh for2.sh
ld mta-aliasesman mta-newaliases mta-rmail zabbix-server
libnssckbi.so.x86_64 mta-mailq mta-newaliasesman mta-sendmail zabbix-web-font
mta mta-mailqman mta-pam mta-sendmailman
alternatives
ld mta-aliasesman mta-newaliases mta-rmail zabbix-server
libnssckbi.so.x86_64 mta-mailq mta-newaliasesman mta-sendmail zabbix-web-font
mta mta-mailqman mta-pam mta-sendmailman
audispd.conf plugins.d
audisp
audispd.conf plugins.d
auditd.conf audit.rules audit-stop.rules rules.d
audit
auditd.conf audit.rules audit-stop.rules rules.d
iprutils
bash_completion.d
iprutils
binfmt.d
chkconfig.d
0hourly
cron.d

...

pure-ftpd
xinetd.d
pure-ftpd
fssnap.d pluginconf.d protected.d vars version-groups.conf
yum
fssnap.d pluginconf.d protected.d vars version-groups.conf
CentOS-Base.repo CentOS-fasttrack.repo CentOS-Vault.repo zabbix.repo
CentOS-CR.repo CentOS-Media.repo epel.repo
CentOS-Debuginfo.repo CentOS-Sources.repo epel-testing.repo
yum.repos.d
CentOS-Base.repo CentOS-fasttrack.repo CentOS-Vault.repo zabbix.repo
CentOS-CR.repo CentOS-Media.repo epel.repo
CentOS-Debuginfo.repo CentOS-Sources.repo epel-testing.repo
web zabbix_agentd.conf zabbix_agentd.d zabbix_server.conf
zabbix
web zabbix_agentd.conf zabbix_agentd.d zabbix_server.conf
[root@aming-01 shell]#

- 还有一个知识点
- 这个for i in 最基本的语句 for i in `seq 1 3`; do echo $i; done 这是最常见常用的一种for循环
- 可以直接把它写成下面这个样子

[root@aming-01 shell]# for i in seq 1 3; do echo $i; done
1
2
3
[root@aming-01 shell]# seq 1 3
1
2
3
[root@aming-01 shell]# for i in 1 2 3; do echo $i; done
1
2
3

- 创建一个aming 目录

[root@aming-01 shell]# mkdir aming
[root@aming-01 shell]# cd aming/
[root@aming-01 aming]# ls
[root@aming-01 aming]# touch 1 2
[root@aming-01 aming]# touch 3\ 4.txt
[root@aming-01 aming]# ls
1 2 3 4.txt
[root@aming-01 aming]# ls 3
ls: 无法访问3: 没有那个文件或目录
[root@aming-01 aming]# ls -l
总用量 0
-rw-r--r-- 1 root root 0 11月 22 21:33 1
-rw-r--r-- 1 root root 0 11月 22 21:33 2
-rw-r--r-- 1 root root 0 11月 22 21:33 3 4.txt

[root@aming-01 aming]# for i in ls ./; do echo $i; done
1
2
3
4.txt
[root@aming-01 aming]#

- 这意味着for循环的时候 它会以空格或者回车作为分隔符
- for 循环,它对象,不管是空格 回车,它都作为一个分隔符

# 20.11 while循环(上)
- 语法 while 条件; do … ; done.
- 每个1分钟检查一下系统负载,当系统的负载大于10的时候,发一封邮件(很显然这是一个监控脚本)
- 案例1

#!/bin/bash
while : // : 表示死循环,或者1,或者 true都是死循环,都是可以的
do
load=w|head -1|awk -F 'load average: ' '{print $2}'|cut -d . -f1 
if [ $load -gt 10 ]
then
/usr/local/sbin/mail.py xxx@qq.com "load is high: $load" 
fi
sleep 30 //休眠30秒,因为检查系统负载,不需要一直去检查,过一会再看
done

- 新建一个脚本

[root@aming-01 aming]# vim while1.sh

#!/bin/bash
while :
do
load=w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1
if [ $load -gt 10 ]
then
/usr/local/sbin/mail.py xxx@qq.com "load high" "$load"
fi
sleep 30
done

~



:wq

- 来把这个脚本拆分出来看下

[root@aming-01 aming]# vim while1.sh

[1]+ 已停止 vim while1.sh
[root@aming-01 aming]# fg
vim while1.sh

[1]+ 已停止 vim while1.sh
[root@aming-01 aming]# w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1
0
[root@aming-01 aming]# w
21:56:36 up 1:00, 2 users, load average: 0.17, 0.09, 0.07
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty1 20:56 1:00m 0.01s 0.01s -bash
root pts/0 192.168.202.1 20:56 4.00s 0.17s 0.01s w
[root@aming-01 aming]# uptime
21:56:40 up 1:00, 2 users, load average: 0.23, 0.10, 0.07
[root@aming-01 aming]# uptime|awk -F 'load average:' '{print $2}'
0.08, 0.08, 0.07
[root@aming-01 aming]# uptime|awk -F 'load average:' '{print $2}'|cut -d. -f1
0
[root@aming-01 aming]# uptime|awk -F 'load average: ' '{print $2}'|cut -d. -f1
0
[root@aming-01 aming]# uptime|awk -F 'load average:' '{print $2}'|cut -d. -f1|sed 's/ //'
0
[root@aming-01 aming]#


- 脚本解释
- w //查看系统负载 ; 
- uptime 可以直接显示 w 系统负载的第一行,就可以省去  head -1 
- head -1   //取第一行
- awk -F 'load average:  ' '{print $2}'  // 以'load average:  '分隔,输出第二段
- cut -d . -f1  // 以  . 为分隔符 取第一段
- 然后来执行下命令

[root@aming-01 aming]# vim while1.sh
[root@aming-01 aming]# sh -x while1.sh

  • true
    ++ w
    ++ awk -F 'load average: ' '{print $2}'
    ++ cut -d . -f1
    ++ head -1
  • load=
  • '[' -gt 10 ']'
    while1.sh: 第 5 行:[: -gt: 期待一元表达式
  • sleep 30

  • true
    ++ head -1
    ++ awk -F 'load average: ' '{print $2}'
    ++ w
    ++ cut -d . -f1
  • load=
  • '[' -gt 10 ']'
    while1.sh: 第 5 行:[: -gt: 期待一元表达式
  • sleep 30
    ^C
    [root@aming-01 aming]#

# 20.12 while循环(下)
- while循环案列2

[root@aming-01 aming]# vim while2.sh

#!/bin/bash
while :
do
read -p "Please input a number: " n
if [ -z "$n" ]
then
echo "you need input sth."
continue //continue 表示结束本次循环,忽略continue之下的代码,直接进行下一次循环
fi
n1=echo $n|sed 's/[0-9]//g'
if [ -n "$n1" ]
then
echo "you just only input numbers."
continue
fi
break // 这表示符合需求,退出这个while循环
done
echo $n









:wq

- 接下来执行下脚本
- 输入空格,提示继续输入数字
- 再次输入数字就 echo 数字

[root@aming-01 aming]# vim while2.sh
[root@aming-01 aming]# sh -x while2.sh

  • :
  • read -p 'Please input a number: ' n
    Please input a number:
  • '[' -z '' ']'
  • echo 'you need input sth.'
    you need input sth.
  • continue
  • :
  • read -p 'Please input a number: ' n
    Please input a number: 2
  • '[' -z 2 ']'
    ++ echo 2
    ++ sed 's/[0-9]//g'
  • n1=
  • '[' -n '' ']'
  • break
  • echo 2
    2
    [root@aming-01 aming]#

20.13 break跳出循环

  • break 常用于循环语句中
  • 跳出整个循环语句,直接结束所有循环
    
    [root@aming-01 aming]# vim break.sh

#!/bin/bash
for i in seq 1 5
do
echo $i
if [ $i -eq 3 ]
then
break
fi
echo $i
done
echo aaaaa
~


:wq

[root@aming-01 aming]# cat break.sh
#!/bin/bash
for i in seq 1 5
do
echo $i
if [ $i -eq 3 ]
then
break
fi
echo $i
done
echo aaaaa
[root@aming-01 aming]#

- 那来执行下脚本break.sh

[root@aming-01 aming]# vim break.sh
[root@aming-01 aming]# sh -x break.sh
++ seq 1 5

  • for i in 'seq 1 5'
  • echo 1
    1
  • '[' 1 -eq 3 ']'
  • echo 1
    1
  • for i in 'seq 1 5'
  • echo 2
    2
  • '[' 2 -eq 3 ']'
  • echo 2
    2
  • for i in 'seq 1 5'
  • echo 3
    3
  • '[' 3 -eq 3 ']'
  • break
  • echo aaaaa
    aaaaa
    [root@aming-01 aming]#

[root@aming-01 aming]# sh break.sh
1
1
2
2
3
aaaaa
[root@aming-01 aming]#


# 20.14 continue结束本次循环
- continue 表示结束本次循环 ,忽略continue之下的代码,直接进行下一次循环

[root@aming-01 aming]# cp break.sh continue.sh
[root@aming-01 aming]# vi continue.sh

#!/bin/bash
for i in seq 1 5
do
echo $i
if [ $i -eq 3 ]
then
continue //这里原来是break 改成 continue
fi
echo $i
done
echo aaaaa
~


:wq

- 再来执行这个continue.sh 

[root@aming-01 aming]# vi continue.sh
[root@aming-01 aming]# sh continue.sh
1
1
2
2
3
4
4
5
5
aaaaa
[root@aming-01 aming]#

- 再看下break.sh 对比

[root@aming-01 aming]# sh break.sh
1
1
2
2
3
aaaaa
[root@aming-01 aming]#


# 20.15 exit退出整个脚本
- exit直接退出脚本

[root@aming-01 aming]# cp continue.sh exit.sh
[root@aming-01 aming]# vi exit.sh

#!/bin/bash
for i in seq 1 5
do
echo $i
if [ $i -eq 3 ]
then
exit
fi
echo $i
done
echo aaaaa
~


:wq

- 来执行下exit.sh

[root@aming-01 aming]# vi exit.sh
[root@aming-01 aming]# sh exit.sh
1
1
2
2
3
[root@aming-01 aming]# sh break.sh
1
1
2
2
3
aaaaa
[root@aming-01 aming]#

- exit还可以定义后面的输出数字

[root@aming-01 aming]# sh exit.sh
1
1
2
2
3
[root@aming-01 aming]# echo $?
0

[root@aming-01 aming]# vi exit.sh

#!/bin/bash
for i in seq 1 5
do
echo $i
if [ $i -eq 3 ]
then
exit 2
fi
echo $i
done
echo aaaaa

[root@aming-01 aming]# sh exit.sh
1
1
2
2
3
[root@aming-01 aming]# echo $?
2


### 扩展
-  shell中的select用法
- select也是循环的一种,它比较适合用在用户选择的情况下。
比如,我们有一个这样的需求,运行脚本后,让用户去选择数字,选择1,会运行w命令,选择2运行top命令,选择3运行free命令,选择4退出。脚本这样实现:

#!/bin/bash
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
case $command in
w)
w
;;
top)
top
;;
free)
free
;;
quit)
exit
;;
*)
echo "Please input a number:(1-4)."
;;
esac
done

-  执行结果如下:

sh select.sh
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit

1) w
2) top
3) free
4) quit
#? 1
16:03:40 up 32 days, 2:42, 1 user, load average: 0.01, 0.08, 0.08
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 61.135.172.68 15:33 0.00s 0.02s 0.00s sh select.sh

#? 3
total used free shared buffers cached
Mem: 1020328 943736 76592 0 86840 263624
-/+ buffers/cache: 593272 427056
Swap: 2097144 44196 2052948
#?


- 我们发现,select会默认把序号对应的命令列出来,每次输入一个数字,则会执行相应的命令,命令执行完后并不会退出脚本。它还会继续让我们再次输如序号。序号前面的提示符,我们也是可以修改的,利用变量PS3即可,再次修改脚本如下:

#!/bin/bash
PS3="Please select a number: "
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
case $command in
w)
w
;;
top)
top
;;
free)
free
;;
quit)
exit
;;
*)
echo "Please input a number:(1-4)."
esac
done

-  如果想要脚本每次输入一个序号后就自动退出,则需要再次更改脚本如下:

#!/bin/bash
PS3="Please select a number: "
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
case $command in
w)
w;exit
;;
top)
top;exit
;;
free)
free;exit
;;
quit)
exit
;;
*)
echo "Please input a number:(1-4).";exit
esac
done