shell脚本编程(八)

shell脚本编程(七)https://blog.csdn.net/xiaochenXIHUA/article/details/156889172?spm=1001.2014.3001.5501

一、while循环语句

1.1、while循环语句

bash 复制代码
#while循环语句的语法
while expr        #执行expr
do                #若expr的退出状态为0,则进入循环,否则退出while循环
    commands      #执行语句块
done              #循环结束标志,返回循环顶部

先执行expr,若其退出状态为0,就执行循环体,执行到关键字【done】后,就回到循环顶部,while命令再次检查expr的退出状态。以此类推,循环将一直继续下去,直到exr的退出状态为非0为止。执行流程图如下:

|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| 序号 | 说明 |
| 1 | while循环语句也称前测试循环语句,它的循环重复执行次数,是利用一个条件控制是否继续重复执行这个语句。while语句与for循环语句相比,无论是语法还是执行的流程,都比较简明易懂。 |
| 2 | while循环语句之所以命名为前测循环,是因为它要先判断此循环的条件是否成立,然后才作重复执行的操作。也就是说,while循环语句执行的过程是:先判断expression的退出状态,若退出状态为0,则执行循环体,执行到关键字done后,就回到循环的顶部,进行下一次循环,否则退出循环执行done后的命令。 |
| 3 | 为了避免死循环,必须保证在循环体中包含循环出口条件,即存在expression的退出状态为非0的情况。 |
[while循环的注意事项]

1.1.1、while循环示例一

bash 复制代码
#while循环语句示例
vi while-guess-number.sh

#【while-guess-number.sh】文件的完整内容
#!/bin/bash
#filename:while-guess-number.sh
#$RANDOM是系统随机数的环境变量,模100运算用于生成1-100的随机整数
randomnum=$((RANDOM%100))
#使用永真循环(while :),条件退出(break)的方式是接收用户的猜测并进行判断
while :
do
        read -p "请输入你要猜的数字(0-99):" answer
        if [ $answer -lt $randomnum  ];then
                echo "你输入的【$answer】小于随机数,请重新输入"
        elif ((answer>randomnum));then
                echo "你输入的【$answer】大于随机数,请重新输入"
        elif [[ $answer -eq $randomnum ]];then
                echo "恭喜你,猜到了随机数【$randomnum】"
                break
        fi
done


#执行脚本
bash while-guess-number.sh

1.1.2、while循环示例二

读取文件的内容

bash 复制代码
#while循环示例二
vi while-readfile.sh

#【while-readfile.sh】文件的完整内容
#!/bin/bash
#filename:while-readfile.sh
file=/etc/yum.repos.d/epel.repo
oldifs=$IFS
while IFS= read -r line
do
        echo $line
done < $file
IFS=$oldifs


#执行脚本
bash while-readfile.sh

1.1.3、while循环示例三

读取文件中每行的多个内容

bash 复制代码
#while循环示例三
vi while-readfile2.sh

#【while-readfile2.sh】文件的完整内容
#!/bin/bash
#filename:while-readfile2.sh
oldIFS=$IFS
#设置默认的IFS分隔符为冒号,且定义了多个变量
while IFS=: read -r user enpass uid gid desc home shell
do
        #只显示UID大于等于500的内容
        [ $uid -ge 500 ] && echo "User $user $enpass ($uid) $gid $desc assigned "$home" home directory with $shell shell."
done < /etc/passwd
IFS=$oldIFS


#执行脚本
bash while-readfile2.sh

1.2、计数器控制的while循环

假定已经准确知道要输入的数据或字符串的数目,在这种情况下可采用计数器控制的while循环结构来处理。

bash 复制代码
#计数器控制的while循环结构
counter=1
while expression
do
    command
    ...
    let command to operate counter
    command
    ...
done
    
bash 复制代码
#计数器控制的while循环
vi while-counter.sh

#【while-counter.sh】文件的完整内容
#!/bin/bash
#filename:while-counter.sh
count=1
while [ $count -lt 12 ];do
        echo $count
        let count+=1
done


#执行脚本
bash while-counter.sh

1.3、结束标记控制的while循环

在linux shell编程中很多时候不知道读入数据的个数,但是可以设置一个特殊的数据来结束while循环,该特殊数据值称为结束标记,其通过提示用户输入特殊字符或数字来操作。当用户输入该标记后结束while循环,执行done后的命令。

bash 复制代码
#结束标记控制的while循环结构
read variable
while [[ $variable != flag ]]
do
    read variable
done
bash 复制代码
#结束标记控制的while循环示例
vi while-endflag.sh

#【while-endflag.sh】文件的完整内容
#!/bin/bash
#filename:while-endflag.sh
echo "请输入:"
read var
while [[ $var != ok ]];do
        echo "当前输入的内容是【$var】"
        read -p "(可输入 ok 结束)请输入:" var
done


#执行脚本
bash while-endflag.sh

1.4、标志控制的while循环

标志控制的while循环使用用户输入的标志的值来控制循环的结束,这样就避免了用户不知道循环结束标记的麻烦。

bash 复制代码
#标志控制的while循环语法
signal=0

while ((signal != 1))
do
    ...
    if expression
    then
        signal=1
    fi
    ...
done
bash 复制代码
#标志控制的while循环示例
vi while-flag2.sh

#【while-flag2.sh】文件的完整内容
#!/bin/bash
#filename:while-flag2.sh

flag=true
read -p "请输入需要计算的最大数字:" inputnum
count=0
sum=0
while [[ $flag != false ]];do
        ((++count))
        let sum+=count
        echo "计算【$count】次后的总数是【$sum】"
        if ((count==inputnum));then
                flag=false
        fi
done
echo "从【1】到【$inputnum】累加后的总数是【$sum】"


#执行脚本
bash while-flag2.sh

二、until循环语句

2.1、until循环语句

bash 复制代码
#until循环语句
until expr        #执行expr
do                #若expr的退出状态非0,则进入循环,否则退出until
    commands      #循环体
done              #循环结束标志,返回循环顶部

在执行while循环时,只要是expr的退出状态为0将一直执行循环体。until命令和while命令类似,但区别是until循环中的expr的退出状态不为0时循环体将一直执行下去,直到退出状态为0时退出循环。

bash 复制代码
#until循环语句示例
vi until.sh

#【until.sh】文件的完整内容
#!/bin/bash
#filename:until.sh
read -p "请输入需要测试是否畅通的IP地址:" ipadd
until ping -c 1 $ipadd >/dev/null 2>&1
do
        sleep 60
done
ssh $ipadd


#测试脚本
bash until.sh

2.2、exit和sleep

bash 复制代码
#exit命令
exit n

#sleep命令
sleep n

【exit】命令用于退出脚本或当前进程【n】是一个从0到255的整数,0表示成功退出,非零表示遇到某种失败而非正常退出。该整数被保存在状态变量【$?】中。

【sleep n】表示暂停几秒钟。

bash 复制代码
#exit与sleep示例
vi until-user-exist-online.sh

#【until-user-exist-online.sh】文件的完整内容
#!/bin/bash
#filename:until-user-exist-online.sh
username=$1
#判断参数是否小于1,小于则给出使用提示
if [ $# -lt 1 ];then
        echo "用法:`basename $0` <username> [<message>]"
        exit 1
fi


#判断当前输入的用户是否在系统中
if grep "^$username:" /etc/passwd >/dev/null
then
        echo "【$username】用户存在"
else
        echo "【$username】用户不存在系统中"
        exit 2
fi

until who|grep "$username" > /dev/null;do
        echo "【$username】用户目前没有登录"
        sleep 5
done


#执行脚本
bash until-user-exist-online.sh
bash until-user-exist-online.sh coffeemilk

三、循环与菜单

3.1、使用while配合case实现菜单

一般情况下可以使用while循环配合case实现循环菜单;而Bash提供了专门的select 循环实现:

《1》select循环主要用于创建菜单;

《2》select是个无限循环:

①通常要配合case 语句处理不同的选单及退出;

②select循环的退出【ctrl+c 强制退出】【直接在循环体内用break命令退出】【用exit命令终止脚本】。

bash 复制代码
#循环与菜单示例
vi while-menu.sh

#【while-menu.sh】文件的完整内容
#!/bin/bash
#filename:while-menu.sh

readonly str="你选择了"
while true;do
        echo "=======script language======"
        echo "1) bash"
        echo "2) perl"
        echo "3) python"
        echo "4) ruby"
        echo "5) I don't konw!(quit)"
        read -p "你最喜欢哪种脚本语言?" lang
        case $lang in
                1) echo "$str【bash】";;
                2) echo "$str【perl】";;
                3) echo "$str【python】";;
                4) echo "$str【ruby】";;
                5) exit
        esac
done


#执行脚本
bash while-menu.sh

3.2、循环结构select

bash 复制代码
#循环结构select语法
select variable in list
do                     #循环开始的标志
    commands           #循环变量每取一次值,循环体就执行一遍
done                   #循环结束的标志

|--------|-----------------------------------------------|
| 序号 | 说明 |
| 1 | select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,等待用户输入 |
| 2 | 菜单项的间隔符由环境变量IFS决定 |
| 3 | 用于引导用户输入的提示信息存放在环境变量PS3中 |
| 4 | 用户直接输入回车将重新显示菜单 |
| 5 | 与for循环类似,省略【in list】时等价于【in "$*"】 |
| 6 | 用户输入菜单列表中的某个数字,执行相应的命令 |
| 7 | 用户的输入被保存在内置变量REPLY中 |
| ||
| select与case: 《1》select是个无限循环,因此要记住用break命令退出循环,或用exit命令终止脚本。也可以按【ctrl+c】退出循环。 《2》select经常与case联合使用; 《3》与for循环类似,可以省略【in list】,是吃使用位置参量。 ||
[循环结构select说明]

3.2.1、select示例一

bash 复制代码
#循环结构select示例一
vi select1.sh

#【select1.sh】文件的完整内容
#!/bin/bash
#filename:select1.sh
clear
PS3="你最喜欢哪种脚本语言?"
select s in bash perl python ruby quit
do
        case $s in
                bash|perl|python|rubu)
                        echo "你选择了【$s】";;
                quit)
                        exit;;
                *)
                        echo "你选择错误,请重试";;
        esac
done


#执行脚本
bash select1.sh

3.2.2、select示例二

bash 复制代码
#循环结构select示例二
vi select2.sh

#【select2.sh】
#!/bin/bash
#filename:select2.sh
clear
PS3="你最喜欢那款操作系统?"
oldIFS=$IFS
IFS='|'
os="Linux|Windows|FreeBSD|MacOS"
select s in $os;do
        case $REPLY in
                1|2|3|4)
                        echo "你选择的是【$s】";;
                *)
                        exit;;
        esac
done
IFS=$oldIFS


#执行脚本
bash select2.sh

3.2.3、select示例三

bash 复制代码
#循环结构select示例三
vi select3.sh


#【slect3.sh】文件的完整内容
#!/bin/bash
#filename:select3.sh
PS3="选择你想要执行的命令:"
cmd="telnet lvm2 python3 lrzsz gcc yum"
clear
select prog in $cmd quit;do
        [[ $prog == quit ]] && exit
        rpm -q $prog >/dev/null 2>&1 && echo "【$prog】已经安装,已安装的详细版本是【`rpm -q $prog`】" || echo "【$prog】未安装"
done



#执行脚本
bash select3.sh
相关推荐
Q16849645152 小时前
知识点-创建、查看和编辑文本文件
linux·运维
小宇的天下2 小时前
Calibre 3Dstack --每日一个命令days11【dangling_ports】(3-11)
linux·运维·服务器
HIT_Weston2 小时前
97、【Ubuntu】【Hugo】搭建私人博客:搜索功能(二)
linux·运维·ubuntu
chen_mangoo2 小时前
HDMI简介
android·linux·驱动开发·单片机·嵌入式硬件
何达维2 小时前
`kubectl top nodes` 或 `kubectl top pods` 返回 `metrics not available yet` 的排查、解决
linux
东皇太星3 小时前
linux 内存管理详解
linux·运维·服务器
JY.yuyu3 小时前
Linux计划任务进程
linux·运维·服务器
single-life3 小时前
Linux 下 部署es+nebula(附带内网部署方式)
linux·运维·elasticsearch·nebula
ICT董老师3 小时前
kubernetes中operator与helm有什么区别?部署mysql集群是选择operator部署还是helm chart部署?
linux·运维·mysql·云原生·容器·kubernetes