shell三种循环语句(for while until)

137 阅读2分钟

for循环语句的结构

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

for 变量名 in 取值列表
do
  命令序列
donefor 遍历 for 变量 in 取值列表   ##注:取值列表默认的分隔符是空格换行  制表符(tab)
    迭代 for ((变量-初始值;变量的取值范围;变量的迭代方式))
        for  ((i-1;i<=10;i++))
        do {  #do和{两种意思相同
        
        done } #done和{两种意思相同

Snipaste_2022-08-25_16-19-19.png

for循环语句的四种格式

for i in 1 2 3 4 5;do echo $i ;donefor i in {1..10};do echo $i ;done         {1..10..2}##结果是奇数
 
for i in $(seq 1 10);do echo $i ;done     $(seq 1 2 10) #seq顺序意思
 
for ( (i=1; i<=10; i++) );do echo $i ;done  
​
for ( (i=1; i<=10; i+=2) ) ;do echo $i ;done
Snipaste_2022-08-25_16-33-56.png

例题:

1.批量添加用户

  • 用户名存放在users.txt文件中,每行一个
  • 判断用户是否存在,如果已存在则不添加
  • 初始密码均设123456
  • 验证脚本

Snipaste_2022-08-25_16-59-21.png

进入/etc/passwd查看用户密码
Snipaste_2022-08-25_17-08-59.png

2.根据IP地址检查主机状态

  • IP地址存放在ipadds.txt文件中 ,每行一个

  • 使用ping命令检测各主机的连通性

    #!/bin/bashfor IP in `cat /root/day3/ips.txt`
    do
      ping -c 3 -i 0.5 -w 2 $IP &> /dev/null
      if [ $? -eq 0 ];then
       echo "$IP is online"
      else
       echo "$IP is offline"
      fi
    done
    

Snipaste_2022-08-25_17-17-17.png

while 循环语句的结构

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

while 条件测试操作
do   #循环开始
  命令序列
let a++   ##while要进行迭代,不然会一直输出,进入死循环
done #循环的结束

Snipaste_2022-08-25_16-23-31.png

Snipaste_2022-08-25_17-21-22.png

实操:

1.批量添加用户

用户名称以stu开头,按数字顺序进行编号

一共添加20个用户,即stu1、stu2....

初始密码为123456

Snipaste_2022-08-25_17-32-48.png Snipaste_2022-08-25_17-33-07.png

2.猜商品价格游戏

通过变量RANDOM获得随机数

提示用户猜测并记录次数,猜中后退出循环

Snipaste_2022-08-25_17-34-18.png

Snipaste_2022-08-25_17-34-53.png

until 循环语句的结构

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

until 条件测试操作
do
  命令序列
done

Snipaste_2022-08-25_16-24-58.png

Snipaste_2022-08-25_17-39-13.png

实操:

使用until循环来监控系统的登录人数,当人数高于3人时则会每隔10秒显示告警信息

Snipaste_2022-08-25_17-44-22.png

Snipaste_2022-08-25_17-46-16.png

计算1-100的和值

Snipaste_2022-08-25_17-49-05.png

例题:

使用循环语句将一个 0到255 之间的十进制数转换成8位数二进制数

第一种方法:

read -p "请输入0-255之间的整数:" num
for i in 128 64 32 16 8 4 2 1
do
  NUM=$[num - i]
  if [ $NUM -lt 0]
  then
    echo -n 0  #不换行输出
  else
    echo -n 1
    num=$[num - i]
   fi
 done
   echo $num

Snipaste_2022-08-26_16-09-08.png

第二种方法:

sum=''
read -p "请输入0-255之间的整数:" num
for i in {1..8}
do
  NUM=$[num % 2]  ##取余
  sum=$NUM$sum    ##字符串追加的意思
  let num/=2      ##取商
done
echo $sum

Snipaste_2022-08-26_16-12-47.png

echo的用法

echo -n 表示不换行输出

echo -e 输出转义字符,将转义后的内容输出到屏幕上

常用的转义字符如下:

转义字符说明
\b转义后相当于退格键(backspace),但是前提是“\b”存在字符。“\b”表示删除前一个字符,“\b\b”表示删除前面两个字符
\c不换行输出,在“\c”后面不存在字符的情况下,作用相当于echo -n,但是当“\b”后面仍然存在字符时,“\c”后面的字符将不会被输出
\n换行输出,被输出的字符从"\n"出开始另起一行
\f换行输出,但是换行后新行的开头位置连接着上一行的行尾
\v换行输出,但是换行后新行的开头位置连接着上一行的行尾
\t转义后表示插入横向制表符,即tab
\r光标移至行首,但是不换行,相当于使用“\r”之后的字符覆盖“\r”之前同等长度的字符,但是当“\r”后面不存在任何字符时,“\r”前面的字符不会被覆盖;当“\r”后面存在的字符大于前面时,“\r”前面的字符全部会被后面替代
\ \在转义符前面加入转义符,代表将后面的转义符转义为符号本身,也就是 \ 有两个作用,一个是可以配一些普通字符实现特殊效果 \n \t \r \c \b 另一个是可以把一些特殊符号转换成普通字符 $ ! . * ^ &
\b 相当于退格键

Snipaste_2022-08-26_16-29-45.png

\c 不换行输出

Snipaste_2022-08-26_16-32-21.png

\n 换行输出

Snipaste_2022-08-26_16-33-37.png

\f=\v 换行输出,换行后新行的开头位置连接着上一行的行尾

Snipaste_2022-08-26_16-35-48.png

\t 制表符显示

Snipaste_2022-08-26_16-36-59.png

\r 光标移至行首 不换行

Snipaste_2022-08-26_16-40-35.png

\表示符号本身

Snipaste_2022-08-26_16-42-29.png

截取字符串 分片

echo ${变量名:下标:长度}

Snipaste_2022-08-26_16-47-01.png

字符串长度

echo ${#变量名}

Snipaste_2022-08-26_16-45-40.png

删除字符串内容

i="1,2,3,4"
echo ${i%, *}
1,2,3
//从最后倒数到最短的匹配部分(用%)后面的逗号的地方被删除
 
echo ${i%%, *}
1
//从最后倒数到最长的匹配部分(用%)后面的逗号的地方都被删除
 
echo ${i#*,}
2,3,4
//从开头到最短的匹配部分(用#)后面的逗号的地方被删除
 
echo ${i##*, }
4
//从开头到最长的匹配部分(用##)后面的逗号的地方被删除

Snipaste_2022-08-26_16-51-54.png

例题:

写一个自动生产8位数随机密码的脚本(大小写字母和数字)

#!/bin/bashSTR="ABCDEFGHIJKMNOPQSTUVWXTZzbcdrfginjklmnopqrstuvwxtz0123456789"
sum=''
for ((i=1;i<=8;i++))
do
  length=${#STR}  字符串长度
  num=$[RANDOM % length]  随机生成数字  
  value=${STR:num:1}     截取字符串
  sum=$sum$value / sum+=$value 追加字符串
done
echo $sum

Snipaste_2022-08-26_17-01-09.png

IFS字段分隔符 for循环

set | grep IFS
IFS=$ '\t\n' 默认包含空格,制表符,换行符    
​
IFS=$'\n' ##修改成只换行
IFS.OLD=$IFS ##保存IFS的原始值
IFS=$IFS_OLD ##还原变量IFS的原始值
演示:

使用for分隔符IFS将echo $PATH中文件 以“:”分隔,并显示出来

Snipaste_2022-08-26_17-18-23.png

使用while读取文件

while read line    #line为变量名
do
...
done < 文件名
​
<command> | while read line
do
..
done

编写能够按照每100行分割文件的脚本

#!/bin/bash#统计文件行数的变量
a=0
#分隔的文件编号
b=1
cat /root/days/text.txt | while read line
do
 let a++
 #统计每50行的变量
 c=$[a % 100]
 #每当一个文件写入满足1000行则迭代文件编号的变量
 if [ $c -eq 0 ];then
   echo $line >> ./test$b.txt
   let b++
 else
   echo $line >> ./test$b.txt
 fi
done

Snipaste_2022-08-28_18-27-19.png

循环语句中的break、exit和continue

break的使用

跳出N层循环,默认不带数字 代表跳出单层循环,N代表N层循环

exit的使用

退出脚本进程,后面携带数字则代表退出脚本进程后返回的状态码

continue的使用

中止本次循环的后续命令操作,但不中止后面循环的操作