前面讲的判断语句if和case只能做判断,可以说只能做一些判断。如果判断结果为假,将执行最后的命令(一般是exit退出脚本),如果不想退出,继续选从零开始小于10以内的次数,择正确的选项,就需要继续回到上面选择,这时就需要循环语句。循环语句可以做类似于一级菜单、二级菜单的选项,直到选择正确的选项,最后可以退出脚本,这就是一个完整的程序。而循环语句有for和while两种,本章讲解的是for语句。
for的语法格式
1. for 变量名 in [取值列表] 2. do 3. 循环命令语句 4. done
语法格式上来看,还是很简单的,我们在来几个简单的案例,让我们更加理解。
for循环案例
案例一:循环创建文件
目的是在根下filedir目录创建100个文件;在执行前先确定有没有该目录,所以就需要用到判断语句,如果没有这个目录则创建,有则不执行,
1. [root@daxia sh]# vim for1.sh 2. #!/bin/bash 3. 4. text=/filedir 5. 6. [ ! -d $text ] && mkdir $text 7. 8. for I in {1..100} 9. do 10. touch ${text}/hehe$I 11. done 12. 13. [root@daxia sh]# sh for1.sh 14. [root@daxia sh]# ls /filedir/
案例二:应用引号或转义符
for循环的取值比较复杂,我们可以使用引号或转义符。比如说下面的file1需要用单引号引起来,但是如果不使用转义符,系统会以为引起来的内容是一起的,不会打印出来单引号。而后面的hello beijing不用引号引起来,系统会以为是两个值,分开打印。
1. [root@daxia sh]# vim for2.sh 2. #!/bin/bash 3. for F in \'file1\' "hello beijing" file4 "hello world" 4. do 5. echo the text is $F 6. done 7. [root@daxia sh]# sh for2.sh 8. the text is 'file1' 9. the text is hello beijing 10. the text is file4 11. the text is hello world
案例三:从变量中取值
在循环里,取值列表可以是变量,先定一个变量,里面添加值,在for里面引用。
1. [root@daxia sh]# vim for3.sh 2. #!/bin/bash 3. List="file1 file2 file3" 4. for I in $List 5. do 6. echo "the text is ${I}" 7. done 8. [root@daxia sh]# sh for3.sh 9. the text is file1 10. the text is file2 11. the text is file3
案例四:从命令中取值
在命令中取值默认以空格为分隔符,可以使用IFS自定义分隔符。
1. [root@daxia sh]# vim for4.sh 2. #!/bin/bash 3. for H in $(cat /etc/hosts) 4. do 5. echo "$H" 6. done 7. [root@daxia sh]# sh for4.sh 8. 127.0.0.1 9. localhost 10. localhost.localdomain 11. localhost4 12. localhost4.localdomain4 13. ::1 14. localhost 15. localhost.localdomain 16. localhost6 17. localhost6.localdomain6
#以冒号做分隔符 IFS=: #以分号做分隔符 IFS=";" #以换行符做字段分隔符 IFS=$'\n'
我们可以看到上面,执行后,原本两行的文本,打印出了很多行。这就很不合理,我们后面把分隔符改成换行作为分隔符。
1. [root@daxia sh]# vim for4.sh 2. #!/bin/bash 3. 4. IFS=$'\n' 5. for H in $(cat /etc/hosts) 6. do 7. echo "$H" 8. done 9. [root@daxia sh]# sh for4.sh 10. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 11. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
案例五:for循环自增自减
我们来感受下自增的变化吧,根据上面几个案例,我们可以在值中写入多个用户,然后再循环创建。但是如果使用自增的话可以指定创建多少,并且不用写那么多的值。下面for语句中的i=1表示初始值为1,i<=10则是表示最多等于10或小于10,i++则是每次循环加一。这样我们就可以创建出十个不同数字的用户了,试想一下,自增还能给我们带来哪些便利呢?
1. [root@daxia sh]# vim for5.sh 2. #!/bin/bash 3. for (( i=1;i<=10;i++ )) 4. do 5. useradd sc$i 6. done 7. [root@daxia sh]# sh for5.sh 8. [root@daxia sh]# tail -10 /etc/passwd 9. sc1:x:1000:1000::/home/sc1:/bin/bash 10. sc2:x:1001:1001::/home/sc2:/bin/bash 11. sc3:x:1002:1002::/home/sc3:/bin/bash 12. sc4:x:1003:1003::/home/sc4:/bin/bash 13. sc5:x:1004:1004::/home/sc5:/bin/bash 14. sc6:x:1005:1005::/home/sc6:/bin/bash 15. sc7:x:1006:1006::/home/sc7:/bin/bash 16. sc8:x:1007:1007::/home/sc8:/bin/bash 17. sc9:x:1008:1008::/home/sc9:/bin/bash 18. sc10:x:1009:1009::/home/sc10:/bin/bash
同时输出1-9的升序和降序,注意:多个值之间是用逗号分隔,结束用分号分隔。
1. [root@daxia sh]# vim for5_1.sh 2. #!/bin/bash 3. for (( a=1,b=9;a<=10;a++,b-- )) 4. do 5. echo "num is $a $b" 6. done 7. [root@daxia sh]# sh for5_1.sh 8. num is 1 9 9. num is 2 8 10. num is 3 7 11. num is 4 6 12. num is 5 5 13. num is 6 4 14. num is 7 3 15. num is 8 2 16. num is 9 1 17. num is 10 0
用另外一种方式来实现升序和降序
1. [root@daxia sh]# vim for5_2.sh 2. #!/bin/bash 3. a=0 4. b=10 5. for i in {1..9} 6. do 7. let a++ 8. let b-- 9. echo "num is $a $b" 10. done 11. [root@daxia sh]# sh for5_2.sh 12. num is 1 9 13. num is 2 8 14. num is 3 7 15. num is 4 6 16. num is 5 5 17. num is 6 4 18. num is 7 3 19. num is 8 2 20. num is 9 1
案例六:批量创建用户
我们先看看RANDOM随机数生成命令,100表示最大生成的随机数,然后+1表示从1开始,如果不+1则随机数可能是0。
[root@daxia sh]# echo $((RANDOM % 100 + 1))
这次脚本写一个批量创建用户,提示用户输入前缀、数量,指定root用户才能执行脚本,密码随机(使用RANDOM命令),前缀不能为空。
1. [root@daxia sh]# vim for6.sh 2. #!/bin/bash 3. if [ ! $UID -eq 0 ] && [ $USER != "root" ];then 4. echo "你不是管理员,执行失败" 5. exit 6. fi 7. read -p "请输入你的用户前缀:" User_a 8. if [ -z $User_a ];then 9. echo "请输入有效的前缀" 10. exit 11. fi 12. read -p "请输入你的用户数量:" User_b 13. if [[ ! $User_b =~ ^[0-9]+$ ]];then 14. echo "请输入整数" 15. exit 16. fi 17. 18. read -p "是否创建用户【y|n】:" yn 19. case $yn in 20. y) 21. for i in $(seq $User_b) 22. do 23. user=${User_a}$i 24. id $user &> /dev/null 25. if [ $? -eq 0 ];then 26. echo "useradd:user $user already exists" 27. else 28. user_pass=$(echo $((RANDOM)) | md5sum | cut -c 2-10 ) 29. useradd $user 30. echo "$user_pass" | passwd --stdin $user &> /dev/null 31. echo "用户:$user 密码:$user_pass " >> /tmp/user.txt 32. echo "useradd:user $user add successfull,密码在/tmp/user.txt" 33. fi 34. done 35. ;; 36. n) 37. exit 38. ;; 39. *) 40. echo "error:请输入【y|n】:" 41. esac 42. 43. [root@daxia sh]# sh for6.sh 44. 请输入你的用户前缀:zhang 45. 请输入你的用户数量:3 46. 是否创建用户【y|n】:y 47. useradd:user zhang1 add successfull,密码在/tmp/user.txt 48. useradd:user zhang2 add successfull,密码在/tmp/user.txt 49. useradd:user zhang3 add successfull,密码在/tmp/user.txt 50. [root@daxia sh]# cat /tmp/user.txt 51. 用户:zhang1 密码:29a106702 52. 用户:zhang2 密码:6ded89b39 53. 用户:zhang3 密码:b984e2b01
自行测试吧,切换用户测试非root用户(非0用户),执行脚本测试是否执行。然后修改脚本成批量删除用户,测试是否成功。
案例七:批量探测主机
批量检查主机(以8.0网段为例),并检查主机22端口是否开启。检查22端口需要使用nmap命令,需要提前安装。为了节省时间,这里就扫描三台主机了。
1. [root@daxia sh]# vim for7.sh 2. #!/bin/bash 3. for i in {100..102} 4. do 5. Ip=192.168.8.$i 6. ping -c 1 -w 1 $Ip &> /dev/null 7. if [ $? -eq 0 ];then 8. echo "$Ip is ok" 9. echo "$Ip" >> /tmp/ip.log 10. else 11. echo "$Ip is down" 12. fi 13. done 14. wait 15. echo "scan host ip is done" 16. echo "scan ssh port is starting" 17. 18. for i in $(cat /tmp/ip.log) 19. do 20. nmap $i |grep "22" &> /dev/null 21. 22. if [ $? -eq 0 ];then 23. echo "$i 22端口已开启" 24. echo "$i 22端口已开启" >> /tmp/port.log 25. fi 26. done 27. 28. [root@daxia sh]# sh for7.sh 29. 192.168.8.100 is ok 30. 192.168.8.101 is down 31. 192.168.8.102 is down 32. scan host ip is done 33. scan ssh port is starting 34. 192.168.8.100 22端口已开启 35. 192.168.8.100 22端口已开启 36. 192.168.8.100 22端口已开启
案例八:随机点名
在一个文档中写入人名,通过过滤筛选出一个。先用wc命令过滤出student.txt中有几个人,来决定循环几次。在通过随机数计算出第几位,并使用sed命令确定人名,循环外面则是计算出的人名高亮显示。
1. [root@daxia sh]# cat student.txt 2. 张三 3. 李四 4. 王五 5. 马六 6. 朱七 7. [root@daxia sh]# vim for8.sh 8. #!/bin/bash 9. num=$(wc -l student.txt|awk '{print $1}') 10. for i in {1..$num} 11. do 12. stu_num=$(( RANDOM % $num + 1 )) 13. sed -n "${stu_num}p" student.txt 14. sleep 0.1 15. done 16. name_stu=$(sed -n "${stu_num}p" student.txt) 17. echo -e "就是你了:\033[32m $name_stu \033[0m" 18. 19. [root@daxia sh]# sh for8.sh 20. 李四 21. 就是你了: 李四 22. [root@daxia sh]# sh for8.sh 23. 朱七 24. 就是你了: 朱七 25. 案例九:随机猜数字 26. 27. [root@daxia sh]# vim for9.sh 28. #!/bin/bash 29. num=$(echo $(( RANDOM % 100 ))) 30. 31. i=0 32. while true 33. do 34. read -p "请输入一个随机数字【1-100】:" sz 35. if [[ ! $sz =~ ^[0-9]+$ ]];then 36. echo "请输入有效的整数" 37. continue 38. fi 39. 40. if [ $sz -gt $num ];then 41. echo "你的数字过大" 42. elif [ $sz -lt $num ];then 43. echo "你的数字过小" 44. else 45. echo "恭喜,你猜对了!!!" 46. break 47. fi 48. let i++ 49. done 50. echo "你总共猜了 $(( $i + 1 )) 次。" 51. [root@daxia sh]# sh for9.sh 52. 请输入一个随机数字【1-100】:50 53. 你的数字过小 54. 请输入一个随机数字【1-100】:80 55. 你的数字过大 56. 请输入一个随机数字【1-100】:70 57. 你的数字过大 58. 请输入一个随机数字【1-100】:60 59. 你的数字过小 60. 请输入一个随机数字【1-100】:65 61. 你的数字过大 62. 请输入一个随机数字【1-100】:63 63. 你的数字过大 64. 请输入一个随机数字【1-100】:62 65. 你的数字过大 66. 请输入一个随机数字【1-100】:61 67. 恭喜,你猜对了!!! 68. 你总共猜了 8 次。 69. [root@daxia sh]#