当前位置:首页 > Liunx > 正文内容

shell循环语法说明-03

邓鹏10个月前 (01-13)Liunx195

#课程目标

  • 掌握for循环语句的基本语法结构

  • 掌握while和until循环语句的基本语法结构

  • 能使用RANDOM变量产生随机数

  • 理解嵌套循环


易混符号小结

符号说明
$( )执行符
`` 反撇号,不是单引号执行符
$[ ]运算符
$(( ))运算符
${ }获取变量并可以做截取
[  ]判断条件
[[  ]]判断条件,里面可以使用正则


循环语句

生活中的循环

image.png

运维维护中经常会出现重复多次执行的工作,如批量建用户,批量删除文件等。利用shell里的循环语句可以很好地帮我们解决问题。


1. for循环

特点: 多用于已知次数的循环(定循环),比如循环100次,循环一个目录下的文件,这些都是有一定次数的。

for循环语法结构

for variable in 1 2 3 4 5
do
 command
 command
 ......
done
for(( expr1;expr2;expr3 ))    # 类C风格的for循环
do
 command
 command
 ......
done

expr1:定义变量并赋初值
expr2:决定是否进行循环(条件)
expr3:决定循环变量如何改变,决定循环什么时候退出

for结构循环数字或字母

#!/bin/bash

for i in 1 2 3 4 5
do
        echo $i
done  {}

其它示例:

# for i in `seq 10`;do echo $i;done
# for i in $(seq 10);do echo $i;done
# for i in `seq 10 -2 1`;do echo $i;done

# for i in {1..10};do echo $i;done
# for i in {0..10..2};do echo $i;done   # 大括号中第3个数字2为一步的长度
# for i in {10..1};do echo $i;done
# for i in {10..1..-2};do echo $i;done

# for ((i=1;i<=5;i++));do echo $i;done
# for ((i=1;i<=10;i+=2));do echo $i;done
# for ((i=10;i>=1;i-=2));do echo $i;done

# for i in {a..z}; do echo $i; done

示例: 用循环实现计算1+2+3的和

#!/bin/bash

sum=0

i=1
sum=$[$sum+$i]
# sum结果为0+1=1

i=2
sum=$[$sum+$i]
# sum结果为1+2=3

i=3
sum=$[$sum+$i]
# sum结果为3+3=6
sum=0
for i in {1..3}
do
        sum=$[$sum+$i]
done
echo $sum


示例:计算1到100的奇数之和

思路:
1. 定义一个变量来保存奇数的和 sum=0
2. 找出1-100的奇数,保存到另一个变量里  i
3. 从1-100中一个一个地找出奇数后,再相加,然后将和赋值给sum变量
4. 循环完毕后,将sum的值打印出来
#!/bin/bash

sum=0
for i in {1..100..2}
do
        sum=$[$sum+$i]
done
echo $sum


循环控制语句

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

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

  • break:打断;马上停止循环,执行==循环体==后面的代码

  • exit:表示直接跳出程序

示例: 改写计算1到100的奇数之和

用continue来改写
sum=0
for i in {1..100}
do
        if [ $[$i%2] -eq 0 ];then
                continue
        fi
        sum=$[$sum+$i]
done
echo $sum

示例: 批量加10个用户, 以student1到student10命名,并统一加一个新组,组名为class,统一改密码为123

#!/bin/bash

groupadd class

# 思路如下
#useradd student1 -G class
#echo 123 | passwd --stdin student1 &> /dev/null


#useradd student2 -G class
#echo 123 | passwd --stdin student2 &> /dev/null


#useradd student3 -G class
#echo 123 | passwd --stdin student3 &> /dev/null
#......

# 把上述思路做成循环
for i in {1..10}
do
        useradd student$i -G class
        echo 123 | passwd --stdin student$i &> /dev/null
done

示例: 批量删除上例建立的10个用户(包括把用户的家目录和邮件目录给删除干净),并删除class组

#!/bin/bash

for i in student{1..10}
do
        userdel -r $i &> /dev/null
done
groupdel class
echo "删除成功"


for结构循环linux文件

比较下列两段的区别:

for file in /etc/*
do
 echo $file
done

for file in $(find /etc)
do
 echo $file
done

示例: 找出/usr/share/doc目录下所有文件名为index.html的文件,把他们拷到/tmp/index目录下,文件名按找到的先后更改,第一个找到的为index.html.1,第二个找到的为index.html.2。。。。以此类推

#!/bin/bash

rm -rf /tmp/index/
mkdir /tmp/index/ -p

count=1
for file in $(find /usr/share/doc/ -name "index.html")
do
 cp $file /tmp/index/index.html.$count
 count=$[$count+1]    # 或者let count++
done

练习: read输入一个目录,查找此目录下所有的死链接文件

#!/bin/bash

read -p "输入一个目录:" dir

if [ ! -d $dir ];then
        echo "你输入的不是目录"
        exit
fi

for file in $(find $dir -type l)
do
        if [ ! -e $file ];then
                echo "$file是死链接文件"
        fi
done


2. while循环

特点:条件为真就进入循环;条件为假就退出循环.多用于不定次数的循环

for循环常用于定循环,while循环常用于不定循环,很多场景两个都可以用

如:  

6点-18点,每个小时整点循环(定了次数,每天都会有6点-18点)

当有太阳,每个小时整点循环(不定次数,天气和季节都会影响是否有太阳)

while循环语法结构

while 条件
do
      条件满足时候:执行动作一
   条件满足时候:执行动作二
      ......
done


示例: 用for循环与while循环做比较打印1-5

for ((i=1;i<=5;i++))   
do
 echo $i
done

i=1
while [ $i -le 5 ]
do
 echo $i
 let i++
done


死循环

死循环就是一直循环,除非使用循环控制语句跳出

while true   条件永远为true,所以会一直循环下去
do
 command
done
其它的死循环写法,不要去记,会上面一种即可
while :
do
 command
done

for (( ;1; ))
do
 command
done

for ((i=1;;i++))
do
 command
done

示例: 每隔1秒钟打印累加的数字

#!/bin/bash

a=1
while true
do
        echo $a
        let a++
        sleep 1      # 等待1秒
done


示例:

写一个30秒同步一次时间,同步服务器为10.1.1.12的脚本,如果同步失败,则使用logger记录到/var/log/messages里,每次失败都记录;同步成功,也进行日志记录,但是成功100次才记录一次。

准备工作:

1555248906996

在时间服务器上操作

# yum install xinetd  -y

# vim /etc/xinetd.d/time-stream
6       disable         = no 把yes改为no

# /etc/init.d/xinetd restart

# netstat -ntlup |grep :37
tcp        0      0 :::37         :::*         LISTEN      6801/xinetd

在客户端上写脚本同步

分析:

  • 不能使用crond来实现(因为crond最少时间间隔单位为1分钟)

  • 每个30s同步一次时间,使用死循环,使用sleep 30实现等待30秒

  • 同步失败记录日志

    • 在do.....done循环体之间加if...else...(判断同步失败还是成功)

  • 同步成功100次发送邮件

    • 统计成功次数——>count=0——>成功1次加+1

# yum install rdate -y

#!/bin/bash

count=0
while true
do
 rdate -s 10.1.1.12 &> /dev/null
 if [ $? -ne 0 ];then
 logger -t "rdate时间同步" "同步失败"
 else
 count=$[$count+1] # 每成功一次计数加1
 if [ $count -eq 100 ];then
   logger -t "rdate时间同步" "同步成功"
 count=0 # 当累计100次记录成功日志后,清零计数
 fi
 fi  
 sleep 30 # sleep等待30秒
done

3. until循环(了解)

特点:直到满足条件就退出循环

until 条件 # 直到满足条件就退出循环
do
 command
 command
 ......
done

比较for与until打印1-5

a=1
until [ $a -gt 5 ]    for ((a=1;a<6;a++))
do do
        echo $a echo $a
        let a++ done
done

建议: until循环结构看得懂就好。因为for与while就完全可以胜任所有的循环,并且后面学习python,python就只有for与while.


随机数

bash默认有一个$RANDOM的变量, 默认范围是0~32767.

使用set |grep RANDOM查看上一次产生的随机数

# echo $RANDOM
19862
# set |grep RANDOM
RANDOM=19862

产生0~1之间的随机数

# echo $[$RANDOM%2]

产生0~2之间的随机数

# echo $[$RANDOM%3]

产生1-2之内的随机数

# echo $[$RANDOM%2+1]

产生50-100之内的随机数

# echo $[$RANDOM%51+50]

产生三位数的随机数

# echo $[$RANDOM%900+100]


示例: 写一个猜数字的小游戏

#!/bin/bash

echo "猜一个1-100的整数,猜对砸蛋:" 

num=$[$RANDOM%100+1]

while true
do
 read -p "请猜:" gnum
    if [ $gnum -gt $num ];then
 echo "大了"
 elif [ $gnum -lt $num ];then
 echo "小了"
 else 
 echo "对了"
 break
 fi
done

echo "砸蛋"


嵌套循环

一个==循环体==内又包含另一个完整的循环结构,称为循环的嵌套。

在外部循环的每次执行过程中都会触发内部循环,直至内部完成一次循环,才接着执行下一次的外部循环。

for循环、while循环和until循环可以相互嵌套。

for i in {a..c}
do
        for j in {1..3}
        do
                echo $i$j
        done
done


示例: 打印出如下结果

*
**
***
****
*****
******
回顾echo命令:
echo默认打印会换行
echo -n打印不换行
echo -e会让/n为换行号,\t为制表符(tab键)

# echo -e "你\n好\t吗"
你
好      吗


#!/bin/bash

for i in $(seq 5) # 循环5行
do
        for j in $(seq $i) # 每行循环次数和行数保持一致
        do
                echo -n "*"
        done
        echo
done

示例:打印出如下结果

1
12
123
1234
12345
#!/bin/bash

for i in $(seq 5)
do
        for j in $(seq $i)
        do
                echo -n $j
        done
        echo
done


课后作业

1, 将/etc/passwd里的用户名分类,分为管理员用户,系统用户,普通用户

#!/bin/bash

rm -rf /tmp/root_user
rm -rf /tmp/system_user
rm -rf /tmp/normal_user

cat /etc/passwd |while read line
do
        user=$(echo $line |cut -d: -f1)
        uid=$(echo $line |cut -d: -f3)
        if [ $uid -eq 0 ];then
                echo "$user" >> /tmp/root_user
        elif [ $uid -ge 1 -a $uid -le 499 -o $uid -eq 65535 ];then
                echo "$user" >> /tmp/system_user
        else
                echo "$user" >> /tmp/normal_user
        fi
done

echo "管理员用户有:"
cat /tmp/root_user
echo
echo "系统用户有:"
cat /tmp/system_user
echo
echo "普通用户有:"
cat /tmp/normal_user

此例后面学习awk后会有更简单的方法

2, 写一个脚本把一个目录内的所有空文件都删除,最后输出删除的文件的个数

方法一:
read -p "输入一个你要删除空文件的目录:" dir

a=0
for i in `find $dir -type f`
do
 [ ! -s $i ] && rm -rf $i && let a++
done

echo "删除的个数为:" "$a" 


方法二:
#!/bin/bash

read -p "输入一个你要删除空文件的目录:" dir

if [ ! -d $dir ];then
        echo "不存在或不是目录,重试"
        exit 0
fi

a=0
for i in `find $dir -size 0 -type f`
do
        rm -rf $i
        let a++
done
echo $a

3, 建立a1, a2, a3, a4, a5, b1, b2, b3, b4, b5。。。。。。。以此类推,一直到e1,e2, e3, e4, e5一共25个用户, 每个用户密码为随机三位数字(100-999), 并将用户名与密码保存到/root/.passwd文件中



扫描二维码推送至手机访问

版权声明:本文由PowerShell中文社区发布,如需转载请注明出处。

本文链接:https://www.powershell.com.cn/?id=30

分享给朋友:

“shell循环语法说明-03” 的相关文章

Shell脚本介绍

Shell脚本介绍

今日目标了解Shell脚本概念磁盘相关命令回顾:磁盘相关命令说明fdisk分msdos分区与要看系统硬盘与分区情况lsblk查看块设备与其挂载情况df -h查看已经挂载的文件系统情况mount也是查看挂载的情况,还能看到挂载的参数(ro或rw等)iostat需要安装sysstat软件包,动态查看磁盘...

shell中正则表达式-05

shell中正则表达式-05

课程目标掌握常用的正则表达式元字符含义掌握sed的删除行操作掌握sed的打印行操作掌握sed的增加行操作掌握sed的修改替换操作正则表达式正则表达式介绍正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过...

CentOS7 服务器上使用T4显卡部署大型AI模型的详细教程

CentOS7 服务器上使用T4显卡部署大型AI模型的详细教程

环境准备服务器配置CPU:Platinum8225c 显卡T4 GPU:T4 16GB  CPU:8核 内存32GB操作系统:Centos7.6英伟达显卡驱动Docker容器环境Docker使用的NVIDIA驱动Ollama容器镜像,Ollama支持的显卡型号:点击查看查看运行环境的资源使...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。