前言

Shell作为一种脚本编程语言,同样了包含了循环,分支等其他程序控制结构,从而能够轻松完成更加复杂、强大的功能。我们今天就来认识for、while、case语句的具体应用。

插个小广告吧,虽然我一开始是拒绝的,课程的内容质量还是可以的,喜欢的小伙伴根据自身需求自行订阅

相关教程传送门:即学即用的Linux核心技能

一、for循环语句

1. for循环语法结构

(一)列表循环

列表for循环:用于将一组命令执行已知的次数

  • 基本语法格式

for variable in {list}docommand command...done
或者
for variable in a b cdocommandcommand...done
 

举例说明:

[root@localhost ~]# for var in {1..10};do echo $var;done
[root@localhost ~]# for var in 1 2 3 4 5;do echo $var;done
[root@localhost ~]# for var in `seq 10`;do echo $var;done
[root@localhost ~]# for var in $(seq 10);do echo $var;done
[root@localhost ~]# for var in {0..10..2};do echo $var;done
[root@localhost ~]# for var in {2..10..2};do echo $var;done
[root@localhost ~]# for var in {10..1};do echo $var;done
[root@localhost ~]# for var in {10..1..-2};do echo $var;done
[root@localhost ~]# for var in `seq 10 -2 1`;do echo $var;done
 

(二)不带列表循环

不带列表的for循环执行时由用户指定参数和参数的个数

  • 基本语法格式

for variabledocommand command...done 
 

举例说明:

#testfor.sh
#!/bin/bash
for var
do
echo $var
done
echo "They are $# parameters after the script"
[root@localhost tmp]# ./testfor.sh 1 2 3 4 5
1
2
3
4
5
They are 5 parameters after the script
[root@localhost tmp]# ./testfor.sh `seq 10`
1
2
3
4
5
6
7
8
9
10
They are 10 parameters after the script
 

(三)类C风格的for循环

  • 基本语法结构

for(( expr1;expr2;expr3 ))docommandcommand…done
for (( i=1;i<=5;i++))doecho $idone
expr1:定义变量并赋初值
expr2:决定是否进行循环(条件判断决定循环什么时候退出)
expr3:决定循环变量如何改变
举例说明:
 # for ((i=1;i<=5;i++));do echo $i;done# for ((i=1;i<=10;i+=2));do echo $i;done# for ((i=2;i<=10;i+=2));do echo $i;done
 

2. 案例

(一)脚本计算1-100奇数和

① 思路

  1. 定义一个变量来保存奇数的和   sum=0

  2. 找出1-100的奇数,保存到另一个变量里  i=遍历出来的奇数

  3. 从1-100中找出奇数后,再相加,然后将和赋值给变量  循环变量  for

  4. 遍历完毕后,将sum的值打印出来

② 落地实现

#!/bin/env bash
# 计算1-100的奇数和
# 定义变量来保存奇数和
sum=0方法1:
#for循环遍历1-100的奇数,并且相加,把结果重新赋值给sum
for i in {1..100..2}
dolet sum=$sum+$i
done
#打印所有奇数的和
echo "1-100的奇数和是:$sum"
方法1:
#!/bin/bash
sum=0
for i in {1..100..2}
dosum=$[$i+$sum]
done
echo "1-100的奇数和为:$sum"方法2:
#!/bin/bash
sum=0
for ((i=1;i<=100;i+=2))
dolet sum=$i+$sum
done
echo "1-100的奇数和为:$sum"方法3:
#!/bin/bash
sum=0
for ((i=1;i<=100;i++))
doif [ $[$i%2] -ne 0 ];thenlet sum=$sum+$ifi或者test $[$i%2] -ne 0 && let sum=$sum+$i
done
echo "1-100的奇数和为:$sum"方法4:
sum=0
for ((i=1;i<=100;i++))
doif [ $[$i%2] -eq 0 ];thencontinueelselet sum=$sum+$ifi或者用test $[$i%2] -eq 0 && continue || let sum=sum+$i 替换if...else
done
echo "1-100的奇数和为:$sum"
 

③ 循环控制语句

循环体: do....done之间的内容

  • continue:继续;表示循环体内下面的代码不执行,重新开始下一次循环

  • break:打断;退出循环体,执行循环体后面的代码

  • exit:表示直接跳出程序

[root@localhost tmp]# cat for2.sh
#!/bin/env bashfor i in {1..5}
dotest $i -eq 2 && break || touch /tmp/file$i
done
echo hello jingyu
 

(二)判断所输整数是否为质数

质数(素数):只能被1和它本身整除的数。2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

① 思路

  1. 让用户输入一个数,保存到一个变量里

  2. 如果能被其他数整除就不是质数——>$num%$i是否等于0$i=2到$num-1

  3. 如果输入的数是1或者2取模根据上面判断又不符合,所以先排除1和2

  4. 测试序列从2开始,输入的数是4——>得出结果$num不能和$i相等,并且$num不能小于$i

② 落地实现

#!/bin/bash
read -p "请输入一个正整数字:" number[ $number -eq 1 ] && echo "$number不是质数" && exit
[ $number -eq 2 ] && echo "$number是质数" && exitfor i in `seq 2 $[$number-1]`do[ $[$number%$i] -eq 0 ] && echo "$number不是质数" && exitdone
echo "$number是质数" && exit
 

(三)批量创建用户

需求:批量加5个新用户,以u1到u5命名,并统一加一个新组,组名为class,统一改密码为123

① 思路

  1. 添加用户的命令 useradd

  2. 判断class组是否存在 grep -w class /etc/group

  3. 根据题意,判断该脚本循环5次来添加用户给用户设置密码,应该放到循环体里面

② 落地实现


/etc/group文件内容:
[root@localhost tmp]# cat /etc/group | head
root:x:0:
bin:x:1:bin,daemon
daemon:x:2:bin,daemon
sys:x:3:bin,adm
adm:x:4:adm,daemon
tty:x:5:
disk:x:6:
lp:x:7:daemon
mem:x:8:
kmem:x:9:
#!/bin/bash
#判断class组是否存在,不存在则添加class组
grep -w class /etc/group &>/dev/null
[ $? -ne 0 ] && groupadd class
#批量创建5个用户
for i in {1..5}
do#添加用户 -G 指定用户所属的附加群组useradd -G class u$i echo 123|passwd --stdin u$i
done方法二:
#!/bin/bash
#判断class组是否存在
cut -d: -f1 /etc/group | grep -w class &>/dev/null
[ $? -ne 0 ] && groupadd class
#循环增加用户,循环次数5次,for循环,给用户设定密码
for ((i=1;i<=5;i++))
douseradd u$i -G classecho 123|passwd --stdin u$i
done方法三:
#!/bin/bash
grep -w class /etc/group &>/dev/null
test $? -ne 0 && groupadd classfor ((i=1;i<=5;i++))
do
useradd -G class u$i && echo 123|passwd --stdin u$i
done

3. 练习

(一) 批量创建用户

需求1:批量新建5个用户stu1~stu5,要求这几个用户的家目录都在/rhome.

#!/bin/env bash
#判断/rhome是否存在 -f 判断文件是否存在并且是一个普通文件
[ -f /rhome ] && mv /rhome /rhome.bak
#/rhome文件不存在且不是一个文件不是一个目录,则创建这个文件
# -a 等价于 &&
test ! -f /rhome -a ! -d /rhome && mkdir /rhome
或者
[ -f /rhome ] && mv /rhome /rhome.bak || [ ! -d /rhome ] && mkdir /rhome
#创建用户,循环5次
for ((i=1;i<=5;i++))
do#-d 指定与用户登录时的主目录useradd -d /rhome/stu$i stu$iecho 123|passwd --stdin stu$i
done
 

(二)局域网内脚本检查主机网络通讯

需求2:写一个脚本,局域网内,把能ping通的IP和不能ping通的IP分类,并分别保存到两个文本文件里。假定局域网的ip地址范围为:10.1.1.1~10.1.1.10

#!/bin/bash
#定义变量
ip=10.1.1
#循环去ping主机的IP
for ((i=1;i<=10;i++))
doping -c1 $ip.$i &>/dev/nullif [ $? -eq 0 ];thenecho "$ip.$i is ok" >> /tmp/ip_up.txtelseecho "$ip.$i is down" >> /tmp/ip_down.txtfi或者[ $? -eq 0 ] && echo "$ip.$i is ok" >> /tmp/ip_up.txt || echo "$ip.$i is down" >> /tmp/ip_down.txt
done[root@localhost tmp]# vim ping.sh
[root@localhost tmp]# chmod +x ping.sh
[root@localhost tmp]# time ./ping.shreal  1m40.068s
user  0m0.022s
sys  0m0.037s
 

延伸扩展:shell脚本并发

并行执行:{程序}& 表示将程序放到后台并行执行,如果需要等待程序执行完毕再进行下面内容,需要加wait

#!/bin/env bash
#定义变量
ip=10.1.1
#循环去ping主机的IP
for ((i=1;i<=10;i++))
do
{ping -c1 $ip.$i &>/dev/nullif [ $? -eq 0 ];thenecho "$ip.$i is ok" >> /tmp/ip_up.txtelseecho "$ip.$i is down" >> /tmp/ip_down.txtfi
}&
done
wait
echo "ip is okey"
[root@localhost tmp]# time ./ping.sh
ip is okeyreal  0m10.061s
user  0m0.011s
sys  0m0.039s
 

并发执行与顺序执行的速度显而易见。

(三)判断闰年

需求3:输入一个年份,判断是否是润年(能被4整除但不能被100整除,或能被400整除的年份即为闰年)

#!/bin/env bash
read -p "Please input year:(2020)" year
if [ $[$year%4] -eq 0 && $[$year%100] -ne 0 ];thenecho "$year is leap year"
elif [ $[$year%400] -eq 0 ];thenecho "$year is leap year"
elseecho "$year is not leap year"
fi
 

4. 总结

  • FOR循环语法结构

  • FOR循环可以结合条件判断和流程控制语句

    • do ......done  循环体

    • 循环体里可以是命令集合,再加上条件判断以及流程控制

  • 循环控制语句

    • continue  继续,跳过本次循环,继续下一次循环

    • break       打断,跳出循环,执行循环体外的代码

    • exit          退出,直接退出程序

二、while循环语句

特点:条件为真就进入循环;条件为假就退出循环

1. while循环语法结构

while 表达式docommand...donewhile  [ 1 -eq 1 ] 或者 (( 1 > 2 ))docommandcommand...done
 

循环打印1-5数字

FOR循环打印:
for ((i=1;i<=5;i++))
doecho $i
donewhile循环打印:
i=1
while [ $i -le 5 ] # -le表示小于d等于
doecho $ilet i++
done
 

2. 应用案例

(一) 脚本计算1-100偶数和

#!/bin/env bash
sum=0
i=2
while [ $i -le 100 ]
dolet sum=$sum+$ilet i+=2
done
echo "1-100以内的偶数之和为:$sum"
 

(二)脚本同步系统时间

① 具体需求

  1. 写一个脚本,30秒同步一次系统时间,时间同步服务器10.1.1.1

  2. 如果同步失败,则进行邮件报警,每次失败都报警

  3. 同步成功,也进行邮件通知,但是成功100次才通知一次

② 思路

  1. 每个30s同步一次时间,该脚本是一个死循环 (rdate命令用于显示其他主机的日期与时间,rdate -s ntp_server 表示把远程服务器ntp_server的时间同步到本地。)

  2. 同步失败发送邮件 (mail -s "主题" 邮件地址)

  3. 同步成功100次发送邮件

③ 落地实现

#!/bin/env bash
count=0 #用于记录发送成功的次数
ntp_server=10.1.1.1
while true
dordate -s $ntp_server &>/dev/nullif [ $? -eq 0 ];thenlet count++if [ $[$count%100] -eq 0 ];thenecho "system date successfull" | mail -s 'check system date'  root@localhost && count=0fielseecho "system date failed" | mail -s 'check system date'  root@localhost  fi
sleep 3
done
 

三、until循环

特点:条件为假就进入循环;条件为真就退出循环

1. until语法结构

until expression   [ 1 -eq 1 ]  (( 1 >= 1 ))
docommandcommand...
done
 

打印1-10数字

i=1
while [ $i -le 10 ]
doecho $ilet i++
donei=1
until [ $i -gt 10 ]
doecho $ilet i++
done
 

2. 应用案例

① 具体需求

  1. 使用until语句批量创建10个用户,要求stu1—stu5用户的UID分别为1001—1005;

  2. stu6~stu10用户的家目录分别在/rhome/stu6—/rhome/stu10

② 思路

  1. 对于stu1—stu5用户的UID设置可用通过命令 useradd -u uid 进行设置;

  2. stu6~stu10用户的家目录可以通过 useradd -d dir_name 进行设置

③ 落地实现

#!/bin/env bash
i=1
until [ i -gt 10 ]
doif [ $i -le 5 ];thenuseradd -u $[1000+$i] stu$i && echo "123" | passwd --stdin stu$ielse[! -d /rhome ] && mkdir /rhomeuseradd -d /rhome/stu$i && echo "123" | passwd --stdin stu$ifi
let i++
done
 

四、家庭作业

  1. 判断/tmp/run目录是否存在,如果不存在就建立,如果存在就删除目录里所有文件

  2. 输入一个路径,判断路径是否存在,而且输出是文件还是目录,如果是链接文件,还得输出是  有效的连接还是无效的连接

  3. 交互模式要求输入一个ip,然后脚本判断这个IP 对应的主机是否 能ping 通,输出结果类似于:Server  10.1.1.20 is Down! 最后要求把结果邮件到本地管理员root@localhost mail01@localhost

  4. 写一个脚本/home/program,要求当给脚本输入参数hello时,脚本返回world,给脚本输入参数world时,脚本返回hello。而脚本没有参数或者参数错误时,屏幕上输出“usage:/home/program hello or world”

  5. 写一个脚本自动搭建nfs服务

Linux从入门到精通系列之SHELL编程循环语句语法及实例详解(forwhileuntil)相关推荐

  1. Linux从入门到精通系列之SHELL编程awk语法结构及案例解析

    前言 AWK 是一种非常强大的文本分析工具.适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行特殊技巧程序设计.对于短消息来说,比如处理话单文件,使用awk就非常方便. 一.awk介绍 1. ...

  2. linux shell编程if语句内判断参数详解【ZT】

                  shell 编程中使用到得if语句内判断参数 –b 当file存在并且是块文件时返回真 -c 当file存在并且是字符文件时返回真 -d 当pathname存在并且是一个目 ...

  3. Linux从入门到精通系列之PPTP

    Linux从入门到精通系列之PPTP 今天我们来说下怎么在linux环境下如何搭建PPTP-×××,PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该 ...

  4. Linux _ Shell编程 — 循环语句

    Linux _ Shell编程 - 循环语句 一.循环语句for的用法 二.循环语句while的用法 三.循环控制语句 一.循环语句for的用法 for 变量名 in 单词表do命令表done 变量依 ...

  5. shell编程数组与冒泡算法排序详解

    shell编程数组与冒泡算法排序详解 一 数组的四种表达方式 二 数组的增删改查操作 三 数组传参 3.1 主程序向函数传数组参数 3.2 从函数返回数组到主程序 四 冒泡算法排序 一 数组的四种表达 ...

  6. 秒懂的shell编程数组与冒泡算法排序详解

    shell编程数组与冒泡算法排序详解 一.数组的四种表达方式 二 .数组的增删改查操作 三 .数组传参 3.1 主程序向函数传数组参数 3.2 从函数返回数组到主程序 四 .冒泡算法排序 一.数组的四 ...

  7. C语言入门篇 | 循环语句和用法(详解版)

    C语言循环语句用法有三种主要形式: for()循环 while()循环 do {} while();循环 for()循环用法: for( e1 ; e2 ; e3 ) //注意三个区域间用分号来分隔, ...

  8. Linux从入门到精通系列之sed命令使用方法

    今日目标 掌握sed的基本语法结构 熟悉sed常用的命令,如打印p,删除d,插入i等 一.文件编辑器知多少 Windows系统 SublimeNotepad++WordTypora Linux系统 v ...

  9. Linux从入门到精通系列之线性表链式存储结构-单链表原理解析

    前言 线性表的链式存储结构的特点就是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以在内存中未被占用的任意位置. 比起顺序存储结构每个元素只需要存储一个位置就可以了.现在链式存储结构中,除了 ...

最新文章

  1. NOI2011 道路修建
  2. double 数组_寻找两个有序数组的中位数
  3. boost::fusion::as_set用法的测试程序
  4. JDBC 创建连接对象的三种方式 、 properties文件的建立、编辑和信息获取
  5. Linux之物理页面的分配
  6. spark官方文档_Spark整合Ray思路漫谈
  7. QtCreate不能使用代码提示功能
  8. 软件先行的英特尔,为开发者们带来了什么?
  9. mysql where子句 参数_MySql——使用where子句过滤数据
  10. 互联网公司的规律.txt
  11. android沉浸状态栏工具,Android 状态栏工具——一行代码实现状态栏...
  12. Python绘图——RGB颜色对照表
  13. 洛谷P1067-多项式输出(模拟好题!)
  14. 杀毒软件简介:杀毒软件原理,教你如何选择一个好的杀毒软件
  15. pci-e服务器显卡性能,旗舰显卡不同PCI-E模式下性能对比测试
  16. 领导力/行为面试必备技能 - STAR 法则
  17. 通信专业实务(三)——接入网
  18. 模拟实现ps aux | grep xxx
  19. 用 Python 快速获取基金持仓增减情况 | 更新版
  20. 程序员进阶的10大黄金法则

热门文章

  1. 对于WIFI版ipad(无GPS芯片)定位功能的释疑
  2. linux下wifi编程(基于netlink和nl80211.h)
  3. 802.11协议基础
  4. linux udp套接字编程获取报文源地址和源端口(二)
  5. Java synchronized 与 lock (Reetrantlock)锁性能比较
  6. 闭式系统蒸汽管径推荐速度_闭式空调系统管径选用表
  7. 智能计米器jk76怎么安装_智能电视怎么安装软件?详细教程一学就会
  8. 华为服务器显示红色的心跳,服务器心跳检查
  9. acid php5,ACID原则
  10. java定义byte_java Byte相关