shell中的流程控制语句

条件选择if语句

选择执行:
注意:if语句可嵌套

判断条件通常为条件测试表达式;也可以是多个命令,以最后一个命令的退出状态为条件值。

单分支

if 判断条件;then
	条件为真的分支代码
fi

双分支

if 判断条件; then
	条件为真的分支代码
else
	条件为假的分支代码
fi

例子

功能:判断是否为管理员

#!/bin/bash
id=`id | awk -F [='('] '{print $2}'`
echo "你的UID为"$id
if ((id == 0));then
echo "你是超级管理员"
else
echo "你是普通用户"
fi

多分支

if 判断条件1; then
	条件1为真的分支代码
elif 判断条件2; then
	条件2为真的分支代码
elif 判断条件3; then
	条件3为真的分支代码
else
	以上条件都为假的分支代码
fi

逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句

范例

#通过输入成绩判断成绩
read -p "请输入你的成绩:" cj
[[ ! "$cj" =~ ^[0-9]{1,3}$ ]] && { echo "输入成绩不合法!";exit; }
if [ "$cj" -ge 0 -a $cj -lt 60 ];then
     echo '不及格!放弃吧!'
elif [ $cj -lt 80 ];then
     echo '刚及格,继续努力!'
elif [ $cj -lt 100 ];then
     echo '很优秀,请保持!'
elif [ "$cj" -eq 100 ];then                                                                   
     echo '完美'
else
     echo '输入的成绩不合理!'
fi

条件判断:case语句

格式

case expr in # expr 为表达式,关键词 in 不要忘!
  pattern1)  # 若 expr 与 pattern1 匹配,注意括号
       commands1 # 执行语句块 commands1
       ;;        # 跳出 case 结构
  pattern2)  # 若 expr 与 pattern2 匹配
       commands2 # 执行语句块 commands2
       ;;        # 跳出 case 结构
       ... ...    # 可以有任意多个模式匹配
  *)         # 若 expr 与上面的模式都不匹配
       commands  # 执行语句块 commands
       ;;        # 跳出 case 结构
esac         # case 语句必须以 esac 终止

case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b

示例:

#!/bin/bash
echo "What is your preferred scripting language?"
echo "1) bash"
echo "2) perl"
echo "3) python"
echo "4) ruby"
echo "5) I do not know !"
read lang
case $lang in
    1) echo "You selected bash"  
	;;
    2) echo "You selected perl"  
	;;
    3) 
	echo "You selected python"
	;;
    4) 
	echo "You selected ruby"  
	;;
    5)  echo "I do not know !"
	;;
esac
#!/bin/bash
echo -n "Do you agree with this? [yes or no]: " 
read yn
case $yn in
  [Yy] | [Yy][Ee][Ss]) 
		echo "Agreed."  
		;;
  [Nn] | [Nn][Oo])   
                 echo "Not agreed."
                 exit 1
                 ;;
   *)            
		echo "Invalid input." 
		;;
esac
#!/bin/bash
case $1 in
   sql) 
   		echo "Running mysql backup using mysqldump tool..." 
   		;;
  sync) 
  		echo "Running backup using rsync tool..."           
  		;;
   git) 
   		echo "Running backup using gistore tool..."         
   		;;
   tar) 
   		echo "Running tape backup using tar tool..."        
   		;;
     *) 
        echo "Backup shell script utility"
        echo "Usage: $0 {sql|sync|git|tar}"
        echo "	sql  : Run mySQL backup utility."
        echo "	sync : Run web server backup utility."	
        echo "	git  : Run gistore backup utility."	
        echo "	tar  : Run tape backup utility." 
        ;;
esac

磁盘监控脚本

#!/bin/bash
max_usage=$(LANG=C df -Ph | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1)
mountlabel=`LANG=C df -Ph|awk '{print $5,$6}'|grep -v Use|sort -n|tail -1|awk '{print $2}'`
case ${max_usage} in
[1-6]*)    
	MSG="All is quiet."   
	;;
[7-8]*)
  	MSG="Start thinking about cleaning out some stuff. "
  	MSG="$MSG There's a partition ${mountlabel} is ${max_usage}% used." 
	;;
9[1-8])
  	MSG="Better hurry with that new disk... "  
  	MSG="$MSG One partition is ${max_usage}% used."  
	;;
99)
  	MSG="I'm drowning here!  There's a partition at ${max_usage}% used"  
	;;
*)
  	MSG="I seem to be running with an nonexitent amount of disk space..."  
	;;
esac
#echo $MSG | mail -s "disk report `date`" root
echo $MSG

在命令行前加LANG=C 是为了让显示的结果在任何机器上都能保持一直

较复杂的综合脚本

#!/bin/bash

cat << EOF
本店菜单如下:
1) 蒸羊羔
2) 蒸熊掌
3) 蒸鹿尾儿
4) 烧花鸭
5) 烧雏鸡
6) 烧子鹅
q)退出结账
EOF
n=0
q=0
manu=''
while true;do
	read -p "请选择数字选项:" p
	case $p in
	1)
		name="蒸羊羔"
		num=50
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	2)
		name="蒸熊掌"
		num=100
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	3)
		name="蒸鹿尾儿"
		num=150
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	4)
		name="烧花鸭"
		num=200
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	5)
		name="烧雏鸡"
		num=200
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	6)
		name="烧子鹅"
		num=280
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	q)
		echo "欢迎下次光临!"
		manu=`echo ${manu}|sed -rn 's@^(.*);$@\1。@p'`
		echo -e "\033[36;1m你选择了${n}道菜!\n分别是:${manu}\n一共\033[0m\033[31;1m${q}\033[0m\033[36;1m元钱!\n\n\033[0m\033[32;1m请问是支付宝还是微信支付!\033[0m"
		exit
		;;
	*)
		echo -e "\033[31;1m输入有误,请重新选择!\033[0m"
		;;
	esac
done

循环

for, while, until

for循环

列表for循环

for 变量名 in 列表;do
	循环体
done

执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束

列表生成方式:
(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:*.sh
(5) 变量引用
$@, $*

范例

for i in $(seq 1 3 10);do echo $i ;done
1
4
7
10

for i in `seq 1 3 10`;do echo $i ;done
1
4
7
10

for i in {10..1..2} ;do echo $i;done
10
8
6
4
2

for i in a b c d ;do echo $i;done
a
b
c
d

for i in *.txt;do echo "文件为$i";done
文件为f1.txt
文件为f2.txt
文件为f3.txt
文件为f4.txt
文件为f5.txt

a=0;for i in `seq 100`;do ((a=a+i));done;echo $a
5050


p=`LANG=C df -h | grep -v "^Filesystem"| awk '{print $5}' | cut -d'%' -f1| sort -rn`
for i in $p;do
	echo $i
done

修改分隔符

注意

如果在"a b 'c d' e 'f g h'"这个字符串中,希望输出的是将各个项注意输出,并且单引号内的字符串作为一项

#!/bin/bash
s="a b 'c d' e 'f g h'"
for i in $s j;do
echo $i;done

#结果
a
b
'c
d'
e
'f
g
h'
j

可以看到,结果并不是想要的

这里就需要修改默认间隔符IFS的值

#!/bin/bash
IFS=%
s="a%b%c d%e%f g h"
for i in $s j;do
echo $i;done

#结果
a
b
c d
e
f g h
j

这里吧IFS设置成%,就可以解决这个问题


利用通配符

for循环中的*表示当前目录下的所有文件名或目录名

$ for i in *;do echo $i ;done
1
1.sh
2.sh
3.sh
4.sh

$ for i in *.sh;do echo $i ;done
1.sh
2.sh
3.sh
4.sh

不带列表for循环

不带列表的for循环执行时由用户指定参数和参数的个数,下面给出了不带列表的for循环的基本格式:

for variable
do
	command 
	command
	…
done

其中do和done之间的命令称为循环体,Shell会自动的将命令行键入的所有参数依次组织成列表,每次将一个命令行键入的参数显示给用户,直至所有的命令行中的参数都显示给用户。

例子

$ vim 4.sh
#!/bin/bash
for args;do
case $args in
  [Yy] | [Yy][Ee][Ss])
        echo $args "同意"  
        ;;
  [Nn] | [Nn][Oo])
        echo $args "不同意"
        ;;
   *)
        echo $args "不明白" 
        ;;
esac
done

$ bash 4.sh Y yes n NY
Y 同意
yes 同意
n 不同意
NY 不明白

可以看到for循环中的args并没有定义,但是也能循环,就是因为收集了执行脚本的参数,相当于$@


for特殊格式

双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作
I=10
((I++))
for 循环的特殊格式:

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
	循环体
done

控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

例子

#!/bin/bash
for ((i=1;i<=10;i++))
do
	echo $i
done

for ((s=0,i=1;i<=100;s+=i,i++))
do
	:
	#单个冒号表示什么都不执行
done
echo sum\(1..100\)=$s

#ping 扫描网段中在线和不在线的ip

>/data/yes.log
>/data/no.log
for i in `seq 1 254`
do
        (ping -c1 -i0.001 -W1 10.50.$1.$i &>/dev/null && echo "10.50.$1.$i ---通">> /data/yes.log|| echo "10.50.$1.$i ---不通">> /data/no.log) &
done
sleep 1.5                     
echo -e "通的:`cat /data/yes.log|wc -l`\n不通:`cat /data/no.log|wc -l`"
exit

#或者
>/data/yes.log
>/data/no.log
for i in `seq 1 254`
do
        {
        ping -c1 -i0.001 -W1 10.50.$1.$i &>/dev/null && echo "10.50.$1.$i ---通">> /data/yes.log|| echo "10.50.$1.$i ---不通">> /data/no.log
        } &
done
sleep 1.5                    
echo -e "通的:`cat /data/yes.log|wc -l`\n不通:`cat /data/no.log|wc -l`"
wait

打印出九九乘法表

#!/bin/bash
echo -e "\t\t\t\033[1;32m九九乘法表\033[0m"                                                                                                                               
for i in `seq 9`;do
        for j in `seq $i` ;do
        g=$[j*i]
        echo -e "${j}x${i}=${g}\t\c"
        done
        echo
done
wait

打印等腰三角形

#!/bin/bash
 
if [[ "$1" =~ ^[0-9]+$ ]];then 
        for i in `seq $1 `;do
                k=`echo $1-$i|bc`
                g=$[2*i-1]
                for j in `seq $k`;do
                        echo -e " \c"
                done
                for n in `seq $g`;do
                        echo -e "\033[1;$[$RANDOM%7+31]m?\033[0m\c"
                done
                echo
        done
else
        echo "请按照形如--$0 数字--格式输入!"
        exit
fi

打印棋盘

#!/bin/bash

n=8
#行数和列数
a=47
#第一行第一种颜色
b=44
#第一行第二种颜色
echo -e "\033[32;1m请选择以下要打印的棋盘类型 \033[0m"

#c是一格相当于标准的行数
read -p "1、标准棋盘 2、中等棋盘 3、巨大棋盘:" no
if [[ "$no" =~ ^[0-9]+$  ]];then
        if [ $no -eq 1  ];then
                c=1
                s='  '
        elif [ $no -eq 2 ];then
                c=2
                s='    '
        elif [ $no -eq 3 ];then
                c=4
                s='        '
        else 
                echo -e "\033[31;1;5m \t\t抱歉,没有这个选项!!! \033[0m"
                exit
        fi
else
        echo -e "\033[31;1m \t\t请不要乱输入!!! \033[0m"
        exit
fi
for i in `seq $n`;do
        for k in `seq $c`;do
                for j in `seq $[n/2]`;do
                        echo -e "\033[${a};1m${s}\033[0m\c"
                        echo -e "\033[${b};1m${s}\033[0m\c"
                done
                echo
        done
        a=$[a^b]
        b=$[a^b]
        a=$[a^b]
done

while循环

while CONDiITION; do
		循环体
done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环

因此:CONDTION一般应该有i循环控制变量;而此变量的值会在循环体不断地被修正
进入条件:CONDITION为true
退出条件:CONDITION为false

例子

$ i=1;while ((i<10));do echo $((i++));done
1
2
3
4
5
6
7
8
9
#!/bin/bash
#$RANDOM是一个系统随机数的环境变量,模100运算用于生成1-100的随机整数
num=$((RANDOM%100)) 
#使用永真循环、条件退出(break)的方式接收用户的猜测并进行判断
while :
do
  read  -p  "Please guess my number [0-99]: "  answer
  if   [ $answer -lt $num ]
  then echo "The number you inputed is less then my NUMBER."
  elif [[ $answer -gt $num ]]
  then echo "The number you inputed is greater then my NUMBER."
  elif ((answer==num))
  then echo "Bingo! Congratulate: my NUMBER is $num." ; break
  fi
done

对数据进行切割

#!/bin/bash
while IFS=: read -r user enpass uid gid desc home shell
do
    # only display if UID >= 500
    [ $uid -ge 500 ] && echo "User $user $enpass ($uid) $gid $desc assigned "$home" home directory with $shell shell."
done < /etc/passwd

10个随机数显示最大最小值

#!/bin/bash

for i in `seq 10`;do
        a[i]=$RANDOM
done
echo "10个随机数分别是:"
for i in `seq 10`;do
        echo -n -e "${a[$i]} "
done
echo
max=${a[1]}
min=${a[1]}
j=2
while [ "$j" -lt 11 ];do
        if [ "$max" -lt "${a[$j]}" ];then
                max=${a[$j]}
        fi
        if [ "$min" -gt "${a[$j]}" ];then
                min=${a[$j]}
        fi
        let j++
done
echo -e  "最大值为${max}\n最小值为$min"


#改进版
i=1
min=$RANDOM
max=$min
echo -n "${min} "
while [ "$i" -lt 10 ];do
        a=$RANDOM
        echo -n "$a "
        if [ "$max" -lt "$a" ];then
                max=$a
        elif [ "$min" -gt "$a" ];then
                min=$a
        fi
        let i++                    
done
echo
echo -e  "最大值为${max}\n最小值为$min"

监控程序,当服务停止时,自动重启服务

#!/bin/bash

while true;do
        if ! `killall -0 httpd &> /dev/null` ;then
                systemctl restart httpd
                echo `date +"%F %T"`"--http服务重启了!"          
        fi
done

可以用true或者冒号代表真

用nohub让脚本在后台运行

nohup /data/checkhttp.sh &> /data/log &

until循环

逻辑刚好与while相反

until CONDITION; do
		循环体
done

进入条件: CONDITION 为false
退出条件: CONDITION 为true

循环控制语句continue(结束本轮循环,进入下一轮循环)

用于循环体中,可结束任何轮的循环
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为
第1层

 while CONDTIITON1; do
		CMD1
		...
		if CONDITION2; then
			continue
		fi
		CMDn
		...
 done

循环控制语句break(直接结束循环)

用于循环体中
break [N]:提前结束第N层循环,最内层为第1层

while CONDTIITON1; do
		CMD1
		...
		if CONDITION2; then
			break
		fi
		CMDn
		...
done

退出整个脚本 exit

exit n

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

延时等待sleep

sleep n

暂停 n 秒钟

菜单(待完善)

#!/bin/bash
#
#
#Author:		XXX
#QQ: 			123456
#Date: 			2021-05-21
#FileName:		menu.sh
#URL: 			http://https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#
#
cat << EOF
本店菜单如下:
1) 蒸羊羔
2) 蒸熊掌
3) 蒸鹿尾儿
4) 烧花鸭
5) 烧雏鸡
6) 烧子鹅
q)退出结账
EOF
n=0
q=0
manu=''
while true;do
	read -p "请选择数字选项:" p
	case $p in
	1)
		name="蒸羊羔"
		num=50
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	2)
		name="蒸熊掌"
		num=100
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	3)
		name="蒸鹿尾儿"
		num=150
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	4)
		name="烧花鸭"
		num=200
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	5)
		name="烧雏鸡"
		num=200
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	6)
		name="烧子鹅"
		num=280
		echo -e "\033[32;1m加一份${name},${num}元/份\033[0m"
		let n++
		if echo ${manu}|egrep "[0-9]+份${name}" &>/dev/null ;then
			a=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\2/p"`
			let a++
			manu=`echo ${manu}|sed -rn "s/^(.*)([0-9]+)(份${name}.*)$/\1${a}\3/p"`
			echo -e "\033[32;1m已经选择${a}份${name}!\033[0m"
		else
			manu="${manu}1份${name};"
		fi
		let q=q+num
		;;
	q)
		echo "欢迎下次光临!"
		manu=`echo ${manu}|sed -rn 's@^(.*);$@\1。@p'`
		echo -e "\033[36;1m你选择了${n}道菜!\n分别是:${manu}\n一共\033[0m\033[31;1m${q}\033[0m\033[36;1m元钱!\n\n\033[0m\033[32;1m请问是支付宝还是微信支付!\033[0m"
		exit
		;;
	*)
		echo -e "\033[31;1m输入有误,请重新选择!\033[0m"
		;;
	esac
done

循环控制shift命令

shift [n]
用于将参量列表 list 左移指定次数,缺省为左移一次
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift

#!/bin/bash
 
while [ "$1" ]
do
 echo $*
 shift
done 

创建无限循环

while true; do
	循环体
done
until false; do
	循环体
done

特殊用法

while循环的特殊用法(遍历文件的每一行)

while read line; do
		循环体
done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line

举例

$ cat <<EOF >test.sh
> 1 2 3
> a b c
> d e f
> EOF
$ cat test.sh 
1 2 3
a b c
d e f
$ while read x y z ;do echo x=$x,y=$y,z=$z;done<test.sh
x=1,y=2,z=3
x=a,y=b,z=c
x=d,y=e,z=f

对数据进行切割

#!/bin/bash
while IFS=: read -r user enpass uid gid desc home shell
do
    # only display if UID >= 500
    [ $uid -ge 500 ] && echo "User $user $enpass ($uid) $gid $desc assigned "$home" home directory with $shell shell."
done < /etc/passwd

对硬盘进行报警

df|sed -rn 's@^([^[:space:]]+).* ([0-9]+)% (.*)$@\1 \2@p'|while read x y;do if [ $y -gt 9 ] ;then echo "${x} 超过阈值,请检查";fi;done
/dev/mapper/centos-root 超过阈值,请检查
/dev/sda1 超过阈值,请检查

换不同ip,对网站进行访问

#!/bin/bash

while true
do
        sed -ri "s@^(IPADD.*\.)[0-9]+@\1$[$RANDOM%240]@" /etc/sysconfig/network-scripts/ifcfg-ens33
        systemctl restart network &> /dev/null
        curl 10.0.0.4 &> /dev/null
        sleep 5                    
done

select循环与菜单

select variable in list
do
  循环体命令
done

select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示 PS3 提示符,等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令
用户输入被保存在内置变量 REPLY
select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环
select 经常和 case 联合使用
与 for 循环类似,可以省略 in list,此时使用位置参量

例子

#!/bin/bash
clear
PS3="What is your preferred OS? "
IFS='|'
os="Linux|Gnu Hurd|FreeBSD|Mac OS X"
select s in $os
do
  case $REPLY in
    1|2|3|4) echo "You selected $s"  ;;
          *) exit ;;
  esac
done

菜单

#!/bin/bash
PS3="请输入数字:"
select menu in 鞋子 帽子 裤子 毛巾 退出
do
        case $REPLY in
                1)
                echo "${menu}2块钱"
                ;;
                2)
                echo "${menu}4块钱"
                ;;
                3)
                echo "${menu}10块钱"
                ;;
                4)
                echo "${menu}不要钱"                                                                                                                                      
                ;;
                5)
                break
                ;;
                *)
                echo "你输错了!"
        esac
done

posted @ 2023-02-23 14:55  厚礼蝎  阅读(44)  评论(0编辑  收藏  举报