shell分支与循环_shell编程基础:分支与循环-程序员宅基地

技术标签: Shell  

1. 条件选择

1.1 条件判断分支介绍

格式

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else
COMMANDS; ] fi
1.1.1 单分支结构
if 判断条件
then
    条件为真的分支代码
fi

# 或者

if 判断条件;then
    条件为真的分支代码
fi
1.1.2 双分支结构
if 判断条件; then 
    条件为真的分支代码
else
    条件为假的分支代码
fi
1.1.3 多分支结构
if 判断条件1; then 
    条件1为真的分支代码
elif 判断条件2; then 
    条件2为真的分支代码
elif 判断条件3; then 
    条件3为真的分支代码
...
else
    以上条件都为假的分支代码
fi

说明:

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

  • if 语句可嵌套

1.2 条件判断 case 语句

格式

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
case 变量引用 in 
PAT1)
    分支1
    ;;
PAT2)
    分支2
    ;;
PAT3)
    分支3
    ;;
easc

case支持glob风格的通配符

* 任意长度任意字符
? 任意单个字符
[] 指定范围内的任意单个字符 
| 或者,如: a|b

示例

[root@centos8 ~/script]#cat yesorno.sh
#!/bin/bash
#
read -p "Do you agree(yes/no)? " INPUT

INPUT=$(echo $INPUT| tr 'A-Z' 'a-z')

case $INPUT in
y|yes)
	echo "You input is YES"
	;;
n|no)
	echo "You input is NO"
	;;
*)
	echo "Input fales,please input yes or no!"
esac

[root@centos8 ~/script]#cat yesorno2.sh
#!/bin/bash
#
read -p "Do you agree(yes/no)? " INPUT
case $INPUT in
[yY]|[Yy][Ee][Ss])
	echo "You input is YES"
	;;
[Nn]|[Nn][Oo])
	echo "You input is NO"
	;;
*)
	echo "Input fales,please input yes or no!"
esac
[root@centos8 ~/script]#

示例

#!/bin/sh
while true
do
    echo "********************************"
    echo "Please select your operation:"
    echo " 1 Copy"
    echo " 2 Delete"
    echo " 3 Backup"
    echo " 4 Quit"
    echo "********************************"
    read op
case $op in
    1)
        echo "your selection is Copy"
        ;;
    2)
        echo "your selection is Delete"
        ;;
    3)
        echo "your selection is Backup"
        ;;
    4)
        echo "Exit ..."
        break
        ;;
    *)
        echo "invalide selection,please try again"
        continue
esac
done

加减乘除

#!/bin/sh
# "select" "case" Uasge
echo "a is 5, b is 3.Please select you method: "
a=5
b=3
select var in "a+b" "a-b" "a*b" "a/b"
do
    break
done
case $var in
    "a+b") echo 'a+b='`expr $a "+" $b`;;
    "a-b") echo 'a-b='`expr $a "-" $b`;;
    "a*b") echo 'a*b='`expr $a "*" $b`;;
    "a/b") echo 'a/b='`expr $a "/" $b`;;
    *) echo "input error..."
esac
sh select_case.sh

归档日志

cat archive_updateserver.sh 
#!/bin/bash
# Parameters
###################################
PREFIX="/search/odin/updateserver"
LOGNAME="ie_log access_log error_alert_log error_log stat_log update_log filter_log updateserver_log"
RESERVE_DAY="3"
###################################
DATE=`date -d "1 days ago" "+%Y%m%d"`
TODAY=`date "+%Y%m%d"`
DATE_0=`date -d"1 days ago" "+%F"`
OLDDATE=`date -d "${RESERVE_DAY} days ago" "+%Y%m%d"`
OLDDATE_0=`date -d "${RESERVE_DAY} days ago" "+%F"`
cd ${PREFIX}
mkdir -p ./log/history
for logtype in ${LOGNAME}
do
    mkdir -p ./log/history/${DATE}/${logtype} 
    case "$logtype" in
        "access_log")
            rm -f ./log/${logtype}/${logtype}_${DATE}.* &
            ;;
        "updateserver_log")
            mv -f ./log/updateserver_log/updateserver.log.${DATE}* ./log/history/${DATE}/${logtype}/
            mv -f ./log/updateserver_log/updateserver.log.wf.${DATE}* ./log/history/${DATE}/${logtype}/
            ;;
        *)
            mv -f ./log/${logtype}/${logtype}_${DATE}.* ./log/history/${DATE}/${logtype}/
            ;;
    esac
    case "$logtype" in
        "access_log")
            echo "ignore tar $logtype"
            ;;
        *)
            cd ./log/history/${DATE}/
            tar czf ${logtype}.tar.gz ${logtype}/  && rm -rf ${logtype} 
            cd ${PREFIX}
            ;;
    esac
done
rm -rf ./log/history/${OLDDATE}

2. 循环

将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件

重复运行次数

  • 循环次数事先已知

  • 循环次数事先未知

常见的循环的命令:for, while, until

2.1 当型和直到型循环语法

2.1.1 while
while COMMANDS; do COMMANDS; done

while CONDITION; 
do 
    循环体
done

说明:

  • CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为 “true”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:CONDTION一般应该有循环控 制变量;而此变量的值会在循环体不断地被修正

  • 进入条件:CONDITION为 true

  • 退出条件:CONDITION为 false

无限循环

while true; do 
    循环体
done


while : ; do 
    循环体
done

总结:while循环特长是守护执行进程,频率小于1分钟

示例1:通过while循环竖向打印10,9,8 。。。1

#!/bin/bash
i=10
while ((i>0))       # 双小括号的用法
do
    echo $i
    ((i--))
done

#!/bin/bash
i=10
while [[ $i > 0 ]]  # 双中括号的用法,注意使用 $i 调用
do
    echo $i
    ((i-2))
done

示例2:计算 1+2+3+…+100 的综合和平均数

[@sjs_115_196 ~]# cat while.sh 
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]
do
    sum=$(($sum+$i))
    i=$(($i+1))
done
echo $sum
echo $(($sum/($i-1)))
[@sjs_115_196 ~]# sh while.sh 
5050
50
[@sjs_115_196 ~]#

示例

# 配置发邮件的邮箱
[root@centos8 ~]#cat .mailrc
set [email protected]
set smtp=smtp.qq.com
set [email protected]
set smtp-auth-password=zrppnudhpwqncaec
set smtp-auth=login
set ssl-verify=ignore
[root@centos8 ~]#
[root@centos8 ~/script]#cat while_diskcheck.sh
#!/bin/bash
#
warning=80
while :;do
	diskwarning=$(df -h|awk '!/Filesystem/{split($5,arr,"%");if(arr[1] > $warning){print arr[1],$NF}}')
	echo -e "Disk will be full from $(hostname -I)\n$diskwarning"| mail -s 'disk warning' [email protected]
	sleep 10
done
[root@centos8 ~/script]#

示例:防止Dos攻击的脚本

cat check_link.sh
#!/bin/bash
#
WARNING=10
touch deny_hosts.txt
while true;do
    ss -nt | sed  -nr '1!s#.* ([0-9.]+):[0-9]+ *#\1#p'|sort |uniq -c|sort |
while read count ip;do
        if [ $count -gt $WARNING ];then
            echo $ip is deny
            grep -q "$ip" deny_hosts.txt || { echo $ip >> deny_hosts.txt;
iptables -A INPUT -s $ip -j REJECT; }
        fi 
    done
    sleep 10 
done
2.1.2 循环until

格式

until COMMANDS; do COMMANDS; done

until CONDITION; do 
    循环体
done

说明

  • 进入条件: CONDITION 为false

  • 退出条件: CONDITION 为true

[root@centos8 ~]#sum=0;i=1;until ((i>100));do let sum+=i;let i++;done;echo $sum
5050
[root@centos8 ~]#

无限循环

until false; do 
    循环体
done

2.2 for循环结构

# CentOS7的for帮助比CentOS8全面
[root@centos7 ~]# help for
for: for 名称 [in 词语 ... ] ; do 命令; done
    为列表中的每个成员执行命令。

    `for' 循环为列表中的每个成员执行一系列的命令。如果没有
    `in WORDS ...;'则假定使用 `in "$@"'。对于 WORDS 中的每
     个元素,NAME 被设定为该元素,并且执行 COMMANDS 命令。

    退出状态:
    返回最后执行的命令的状态。
for ((: for (( 表达式1; 表达式2; 表达式3 )); do 命令; done
    算术 for 循环。

    等价于
    	(( EXP1 ))
    	while (( EXP2 )); do
    		COMMANDS
    		(( EXP3 ))
    	done
    EXP1、EXP2 和 EXP3都是算术表达式。如果省略任何表达式,
    则等同于使用了估值为1的表达式。

    退出状态:
    返回最后执行的命令的状态。
[root@centos7 ~]#
2.2.1 格式1
for NAME [in WORDS ... ] ; do COMMANDS; done

#方式1
for 变量名 in 列表;do
    循环体
done

#方式2
for 变量名 in 列表 
do
    循环体
done
 

提示:在此结构中“in 变量取值列表”可省略,省略时,相当于in“ @ ” , 使 用 f o r i 就 相 当 于 使 用 f o r i i n " @”,使用for i就相当于使用for i in " @使fori使foriin"@"

执行机制:

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

  • 如果省略 [in WORDS … ] ,此时使用位置参量

for 循环列表生成方式:

  • 直接给出列表

  • 整数列表

{
    start..end}                 # 序列方式:for i in {1..5};do echo $i;done 

$(seq [start [step]] end)    # 输出奇数:for i in $(seq 1 2 10);do echo $i;done
  • 返回列表的命令
$(COMMAND)
  • 使用glob,如:*.sh

  • 变量引用,如: @ , @, @*,$#

示例1:自定义分隔符,使用完成后恢复为默认的分隔符

#!/bin/bash
var="hello,world,!,!,!"
oldIFS=$IFS
IFS=,
for item in $var
do
    echo $item
done
IFS=$oldIFS

示例2:100 以内奇数之和

[root@centos8 ~]#sum=0;for i in {1..100..2};do let sum+=i;done;echo sum=$sum
sum=2500
[root@centos8 ~]#seq -s+ 1 2 100 | bc
2500
[root@centos8 ~]#echo {1..100..2}|tr ' ' + | bc
2500
[root@centos8 ~]#sum=0;for i in $(seq 1 2 100);do let sum+=i;done;echo sum=$sum
sum=2500
[root@centos8 ~]#

示例3:计算1+2+3+…+100的综合和平均数

[@sjs_115_196 ~]# cat test.sh
#!/bin/bash
sum=0
n=0
for i in `seq 100`
do 
    sum=$(($sum+$i))
    n=$(($n+1))
done
echo "相加综合":$sum
echo "平均数":$(($sum/$n))
[@sjs_115_196 ~]# sh test.sh
相加总和:5050
平均数:50
[@sjs_115_196 ~]#


[root@centos8 ~]#seq -s+ 100 |bc
5050
[root@centos8 ~]#echo {1..100}|tr ' ' + | bc
5050
[root@centos8 ~]#seq 100 | paste -sd + | bc
5050
[root@centos8 ~]#

示例:批量创建10个系统账号并设置随机密码

cat for_user.sh
#!/bin/bash
#
for n in $(seq -w 10)
do
    id user${n} >/dev/null 2>&1 && echo $user is exist || {
     useradd user$n; echo user$n is created; }
    pass=$(cat /dev/urandom | tr -dc '[:alnum:]' |head -c12)
    echo "$pass" | passwd --stdin user${n} &>/dev/null
    echo -e "user:user${n} pass:${pass}" >> /tmp/useradd.log
   echo "user${n} is created"
done

非交互模式修改密码

echo "password" | passwd --stdin username
#
useradd -d /search/dev -m adpc; echo 'adpc2015' | passwd --stdin adpc
useradd -d /search/users/for_adr -m for_adr;echo 'for_adr2015' | passwd --stdin for_adr
useradd -d /search/users/for_add -m for_add;echo 'for_add2015' | passwd --stdin for_add
useradd -d /search/ADQuery -m op_biz;echo 'op_biz2015' | passwd --stdin op_biz
useradd -d /search/dev -m worker;echo 'apecblue' | passwd --stdin worker

示例:99乘法表

[@sjs_115_196 ~]# cat test.sh
#!/bin/bash
for i in `seq 9`
do
    for j in `seq 9`
    do
        [ $j -le $i ] && echo -n "$j x $i = $(($i*$j)) "   # -n:不换行
    done
    echo ""
done
[@sjs_115_196 ~]# sh test.sh
1 x 1 = 1 
1 x 2 = 2 2 x 2 = 4 
1 x 3 = 3 2 x 3 = 6 3 x 3 = 9 
1 x 4 = 4 2 x 4 = 8 3 x 4 = 12 4 x 4 = 16 
1 x 5 = 5 2 x 5 = 10 3 x 5 = 15 4 x 5 = 20 5 x 5 = 25 
1 x 6 = 6 2 x 6 = 12 3 x 6 = 18 4 x 6 = 24 5 x 6 = 30 6 x 6 = 36 
1 x 7 = 7 2 x 7 = 14 3 x 7 = 21 4 x 7 = 28 5 x 7 = 35 6 x 7 = 42 7 x 7 = 49 
1 x 8 = 8 2 x 8 = 16 3 x 8 = 24 4 x 8 = 32 5 x 8 = 40 6 x 8 = 48 7 x 8 = 56 8 x 8 = 64 
1 x 9 = 9 2 x 9 = 18 3 x 9 = 27 4 x 9 = 36 5 x 9 = 45 6 x 9 = 54 7 x 9 = 63 8 x 9 = 72 9 x 9 = 81 
[@sjs_115_196 ~]#

另外几种写法:

[root@centos8 ~]#cat for3.sh
#!/bin/bash
#
for j in $(seq 9)
do
	for i in $(seq $j)
	do
		echo -e "\E[1;$[RANDOM%7+31]m$i"x"$j=$[i*j]\E[0m\t\c"
	done
	echo
done
[root@centos8 ~]#bash for3.sh
1x1=1
1x2=2	2x2=4
1x3=3	2x3=6	3x3=9
1x4=4	2x4=8	3x4=12	4x4=16
1x5=5	2x5=10	3x5=15	4x5=20	5x5=25
1x6=6	2x6=12	3x6=18	4x6=24	5x6=30	6x6=36
1x7=7	2x7=14	3x7=21	4x7=28	5x7=35	6x7=42	7x7=49
1x8=8	2x8=16	3x8=24	4x8=32	5x8=40	6x8=48	7x8=56	8x8=64
1x9=9	2x9=18	3x9=27	4x9=36	5x9=45	6x9=54	7x9=63	8x9=72	9x9=81
[root@centos8 ~]#

# 语法1实现
for i in {
    1..9};do
    for j in `seq $i`;do
        echo -e "${j}x$i=$((j*i))\t\c"
    done
    echo
done

# 语法2实现 
for((i=1;i<10;i++));do
    for((j=1;j<=i;j++));do
        echo -e "${j}x$i=$((j*i))\t\c"
    done
    echo
done

# awk的写法:
awk 'BEGIN{for(i=1;i<=9;i++){for(j=1;j<=i;j++)printf j"x"i"="j*i"\t";print}}'
2.2.2 C 语言型 for 循环结构

双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash Shell实现C语言风格 的变量操作

for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done

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

说明:

  • 控制变量初始化:仅在运行到循环代码段时执行一次

  • 控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

示例

[root@centos8 ~/script]#cat sum.sh
#!/bin/bash
#
for((sum=0,i=1;i<=100;i++))
do
	let sum+=i
done
echo sum=$sum

for((sum=0,i=1;i<=100;sum+=i,i++))
do
	true
done
echo sum=$sum

sum=0
for((i=1;i<=100;i++))
do
	((sum+=i))
done
echo sum=$sum
[root@centos8 ~/script]#bash sum.sh
sum=5050
sum=5050
sum=5050
[root@centos8 ~/script]#

示例:生成进度

[root@centos8 ~/script]#for ((i = 0; i <= 100; ++i)); do printf "\e[4D%3d%%" $i;sleep 0.1s; done
100%[root@centos8 ~/script]#

示例

[root@centos8 ~/script]#for((;;));do echo for;sleep 1;done
for
for
for
for
for
for
^C
[root@centos8 ~/script]#

示例:

failcount=0
for((i=1;i<=3;i++))
do
    wget -T 5 --tries=1 --spider http://${1} > /dev/null 2>&1
    [ $? -ne 0 ] && let failcount+=1;
done


if [ $failcount -gt 1 ];then
    retval=1
    now_time=`date +"$m-%d %H:%M:%S"`    
fi

2.3 break continue exit

break;continue;exit:一般用于循环结构中控制循环的走向:

2.3.1 循环控制语句 continue

continue [N]:N 表示退到第 N 层继续循环,如果省略 N 表示跳出本次循环,忽略本次循环的剩余代码,进入循环的下一个循环,最内层为第 1 层

格式

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

示例:continue的用法,跳出本次循环

[@sjs_115_196 ~]# cat test.sh
#!/bin/bash
for ii in `seq 3`
do
    for i in `seq 3`
      do
        if [ $i -eq 2 ];then
          continue
        fi
        echo $i
    done
    echo "this is ii:$ii"
done
[@sjs_115_196 ~]# sh test.sh
1
3
this is ii:1
1
3
this is ii:2
1
3
this is ii:3
[@sjs_115_196 ~]#
2.3.2 循环控制语句 break

break [N]:N 表示跳出循环的层数,如果省略 N 表示跳出整个循环,最内层为第 1 层

格式

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

示例:break的用法,break只能用于循环,跳出整个(break所在的那层)循环

[@sjs_115_196 ~]# cat test.sh
#!/bin/bash
for ii in `seq 5`
do
    for i in `seq 5`
      do
        if [ $i -eq 3 ];then
          break
        fi
        echo $i
    done
    echo "this is ii:$ii"
done
[@sjs_115_196 ~]# sh test.sh
1
2
this is ii:1
1
2
this is ii:2
1
2
this is ii:3
1
2
this is ii:4
1
2
this is ii:5
[@sjs_115_196 ~]#
2.3.3 循环控制语句 exit

exit [N] : 退出当前 shell 程序,并返回 N,N 可以省略

示例

[@sjs_115_196 ~]# cat test.sh
#!/bin/bash
for((i=1;i<=5;i++))
do
    if [ "$i" -eq 3 ];then
    #    continue
    #    break
        exit 
    fi
    echo "$i"
done
[@sjs_115_196 ~]# sh test.sh
1
2
[@sjs_115_196 ~]# 

示例:exit的用法,退出当前shell程序

[@sjs_115_196 ~]# cat test.sh
#!/bin/bash
for ii in `seq 5`
do
    for i in `seq 5`
      do
        if [ $i -eq 3 ];then
            exit    
        fi
        echo $i
    done
    echo "this is ii:$ii"
done
[@sjs_115_196 ~]# sh test.sh
1
2
[@sjs_115_196 ~]#

示例:循环检查最近几分钟日志是否滚动

for((i=1;i<=15;i++))
do
    cmd="/usr/bin/find $log_dir -type f -mmin -$interval"
    ssh -oConnectTimeout=60 "${IP}" "${cmd}" < /dev/null > $check_temp
    filefound=`cat $check_temp | wc -l`
    rm -rf $check_temp
    if [ -z "$filefound" -o $filefound -eq 0 ]; then
        sleep 60
        continue
    else
        return 0
    fi
done
return 1

示例:检查web站点目录下所有文件是否被恶意篡改,如果有就打印改动的文件名(生产环境用MD5验证)

#!/bin/bash
for f in `ls *.log`;do wc -L $f;done > cc.txt
[ -f /etc/rc.d/init.d/functions ] && . /etc/rc.d/init.d/functions
for f in `ls *.log`
do
    if [ `cat $f|wc -L` -ne `grep $f c.txt |awk '{print $1}'` ];then
        action "$f" /bin/false
    else
        action "$f" /bin/true
    fi
done

find /etc/ -type f -name "*" -exec md5sum {} >/root/checkmd5.db \;
#!/bin/bash
check_dir=/etc
if [[ -e /root/checkmd5.db ]];then
    md5sum -c /root/checkmd5.db>/root/result.db 2>/dev/null
    egrep -i "FAILED" /root/result.db >/root/err.log
    if [[ ! -s /root/err.log ]];then
        mail -s "$(uname -n) $(date +%F) weberr" [email protected]</root/err.log
    fi
fi

3. 循环控制 shift 命令

shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。

参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift

[root@centos8 ~/script]#cat doit.sh
#!/bin/bash
#
while (( $# > 0 ))
do
	echo $*
	shift
done
[root@centos8 ~/script]#bash doit.sh a b c d
a b c d
b c d
c d
d
[root@centos8 ~/script]#

示例

[root@centos8 ~/script]#cat shift.sh
#!/bin/bash
#
until [ -z "$1" ]
do
	echo "$1"
	shift
done
[root@centos8 ~/script]#bash shift.sh a b c d
a
b
c
d
[root@centos8 ~/script]#

示例:用shift实现值的累加

cat test.sh
#!/bin/bash
if [ $# -le 0 ];then
	echo -e "\033[31mnot engouth paramters\033[0m"
	exit
fi
#用shift实现值的累加
sum=0
while [ $# -gt 0 ]
do
	sum=$(($sum+$1))
	shift
done
echo $sum

$ sh test.sh 1 2 3 4 5
15

4. while 特殊用法 while read

while 循环的特殊用法,遍历文件或文本的每一行

方式一:按行读入

exec<file
sum=0
while read line
do
    cmd
done

方式二:按行读入

cat ${FILE_PATH} | 
while read line
do
    cmd
done

方式三:

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

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

示例

[root@centos8 ~]#echo xufengnian | read NAME;echo $NAME

[root@centos8 ~]#echo xufengnian | while read NAME;do echo $NAME;done
xufengnian
[root@centos8 ~]#echo xufengnian | { read NAME; echo $NAME; }
xufengnian
[root@centos8 ~]#echo xufengnian | ( read NAME; echo $NAME )
xufengnian
[root@centos8 ~]#echo xu feng nian | ( read X Y Z; echo $X $Y $Z )
xu feng nian
[root@centos8 ~]#echo xu feng nian | while read X Y Z; do echo $X $Y $Z;done
xu feng nian
[root@centos8 ~]#

示例

[root@centos8 ~]#cat while_read_check_dos.sh
#!/bin/bash
#
MAX=3
lastb | sed -rn '/ssh:/s@.* ([0-9.]{1,3}{3}[0-9]{1,3}) .*@\1@p'|sort |uniq -c | while read count ip ;do
    if [ $count -gt $MAX ];then
        iptables -A INPUT -s $ip -j REJECT
	fi
done
[root@centos8 ~]#

示例:查看/sbin/nologin的shell类型的用户名和UID

[root@centos8 ~]#cat while_read_passwd.sh
#!/bin/bash
#
while read line
do
	if [[ "$line" =~ /sbin/nologin$ ]];then
		echo $line | awk -F':' '{print $1,$3}'
	fi
done < /etc/passwd
[root@centos8 ~]#

5. 循环与菜单 select

格式

select NAME [in WORDS ... ;] do COMMANDS; done

select variable in list ;do 
    循环体命令
done

说明:

  • select 循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示 PS3 提示符,等待用户输入

  • 用户输入菜单列表中的某个数字,执行相应的命令

  • 用户输入被保存在内置变量 REPLY 中

  • select 是个无限循环,因此要用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环

  • select 经常和 case 联合使用

  • 与 for 循环类似,可以省略 in list,此时使用位置参量

示例

[root@centos8 ~/script]#cat select.sh
#!/bin/bash
#
sum=0
ps3="Your position is(1-6): "
select MENU in CEO CTO CFO CMO COO END;do
case $REPLY in
1)
	echo $MENU The salary is 100000
	let sum+=100000
	;;
2)
	echo $MENU The salary is 80000
	let sum+=80000
	;;
3)
	echo $MENU The salary is 70000
	let sum+=70000
	;;
4)
	echo $MENU The salary is 66800
         let sum+=66800
	;;
5)
	echo $MENU The salary is 66666
	let sum+=66666
	;;
6)
	echo "end"
	break
	;;
*)
	echo "Wrong input, please try again"
	;;
esac
done
echo "The total cost: $sum"
[root@centos8 ~/script]#bash select.sh
1) CEO
2) CTO
3) CFO
4) CMO
5) COO
6) END
#? 1
CEO The salary is 100000
#? 2
CTO The salary is 80000
#? 3
CFO The salary is 70000
#? 6
end
The total cost: 250000
[root@centos8 ~/script]#
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_56752399/article/details/115558407

智能推荐

CUDA与cuDNN安装及tensorflow-gpu2.1下载_cudnn下载清华源-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏14次。1、CUDA1.1、查看电脑显卡及驱动版本1.2、下载安装包1.3、安装步骤2、cuDNN2.1、下载安装包2.2、安装步骤3、环境变量配置4、tensorflow-gpu2.1下载一、CUDA下载及安装1、查看电脑显卡及驱动版本打开NVIDIA控制面板,可查看显卡及驱动版本,如图所示:2、根据自己驱动版本及下表来下载对应的CUDA温馨提示:可以更新显卡驱动版本用来下........._cudnn下载清华源

【java毕业设计】基于java+Lucene+Tomcat的搜索引擎设计与实现(毕业论文+程序源码)——搜索引擎_论文是基于lucene,毕设可以用es写吗?-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏11次。大家好,今天给大家介绍基于java+Lucene+Tomcat的搜索引擎设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。文章目录:搜索引擎的定义就是指按照既定的策略与方法,采取相关的计算机程序,通过在互联网中进行寻找信息,并显示信息,最后把找到的信息进行整理和筛选,为搜索引擎的使用者提供检索信息的服务,终极目标是为了提供给使用者,他所搜索信息相关的资料的计算机系统。搜索引擎的种类繁多,既可以进行全文的索引,还可以进行目录的索引,不仅有集合式的搜索引擎,还有垂直搜索的引擎以及元搜索引擎。除此之外,_论文是基于lucene,毕设可以用es写吗?

基于C语言的小型超市库存与销售管理系统_c语言小型超市管理系统分析-程序员宅基地

文章浏览阅读464次,点赞2次,收藏7次。管理员可浏览某天的或日期区间内的所有销售记录,可对指定日期区间内的销售记录进行综合统计,统计每种商品的销量、收入,统计总收入,可通过销量、销售额筛选统计结果。管理员和售货员可对库存内商品进行销售,对销售请求进行检查,销售后对库存相应商品的余量进行更新,同时记录销售的商品信息、销售时间,更新销售记录数据文件。管理员可手动添加商品,也可从文件中批量导入商品,可查看库存内的全部商品信息,对于库存内商品数为 0 的商品可进行批量清理。管理员用户可浏览系统内所有的用户的账号、密码、权限类别,可添加用户,可删除用户。_c语言小型超市管理系统分析

没有android:padding属性,android自定义无上下padding的textview-程序员宅基地

文章浏览阅读144次。因为工作需要需要无上下padding的textview,经过查阅资料,很多说xml中的配置includefontpadding=false,但无法实现0 padding的需要。也有说通过设置负数的marginTop实现,但是不同字体,需要设置的值不同(因为自带的padding也不同),因此自己写了一个自定义的无padding类。http://blog.csdn.net/chenkai1992041..._不设置padding android

Apache Calcite 为什么能这么流行-程序员宅基地

文章浏览阅读1.5k次。这张图上列的,是直接使用 Apache Calcite 或者至少相关联的项目。大家肯定能在里面找到很多自己熟悉的项目。那 Apache Calcite 究竟是干嘛的,又为..._calcite用的人多吗

360服务器linux版,360浏览器Linux版-程序员宅基地

文章浏览阅读2.1k次。原文来自:https://bbs.360.cn/thread-15529293-1-1.html 【Ubuntu & Deepin 系统】下载链接:https://yunpan.360.cn/surl_yHYBghptmsK (提取码:347d); 【Deepin(龙芯_MIPS64) 】下载链接:https://yunpan.360.cn/surl_yFvrPRipiFU (提取码:c9..._360浏览器;inux 专业版注册码

随便推点

第二百五十八节,Tornado框架-逻辑处理get()方法和post()方法,初识模板语言-程序员宅基地

文章浏览阅读181次。Tornado框架-逻辑处理get()方法和post()方法,初识模板语言 Tornado框架,逻辑处理里的get()方法,和post()方法get()方法,处理get方式的请求post()方法,处理post方式的请求self.get_argument()接收get方式或post方式请求传值,参数是要接收值的名称,如表单传值接收表单数据#!/usr/bin/env python..._tornado 接收post

如何基于阿里云ECS快速搭建Docker环境_如何在阿里云esc上构建容器-程序员宅基地

文章浏览阅读597次。本教程介绍如何基于阿里云ECS快速搭建Docker环境,并使用Docker部署一个Nginx服务,通过本教程的操作,您可以基于阿里云ECS实例快速搭建一个Docker环境,并在Docker环境中部署一个Nginx服务。背景知识容器技术容器是一个允许我们在资源隔离的过程中,运行应用程序和其依赖项的 、轻量的 、操作系统级别的虚拟化技术, 运行应用程序所需的所有必要组件都打包为单个镜像,这个镜像是可以重复使用的。当镜像运行时,它是运行在独立的环境中,并不会和其他的应用共享主机操作系统的内存、CPU或_如何在阿里云esc上构建容器

编写程序C语言 用递归法求n,用C语言编写一个递归程序用来计算:1*2+2*3+3*4+.+(n-1)*n...-程序员宅基地

文章浏览阅读6.5k次。用C语言编写一个递归程序用来计算:1*2+2*3+3*4+.+(n-1)*n以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!用C语言编写一个递归程序用来计算:1*2+2*3+3*4+.+(n-1)*nint fun(int n){if(n==2){return 2;}else{return fun(n-1)+(n-1)*..._对给定的m,编写一个函数求满足1*2+2*3+3*4+..(n-1)*n<=m的最大的n。

JSP简介_jsp引擎有什么作用-程序员宅基地

文章浏览阅读2.2k次,点赞3次,收藏22次。JSP简介一,JSP引擎1,JSP引擎是指支持JSP的Web服务器或Web容器。2,JSP引擎作用是把JSP标签、JSP页中的Java代码甚至连同静态HTML内容先转换成为大块的Java代码,然后Servlet被JSP引擎自动地编译成Java字节码,最后生成的整个页面信息返回给客户端。二,JSP执行过程1,Web容器处理JSP文件请求需要经过以下阶段:① 请求:客户端向服务器发送请求② 翻译阶段:JSP文件会被Web容器中的JSP引擎转换成Java源码。③ 编译阶段:Java源码会被编译成_jsp引擎有什么作用

CodeForces 982 C Cut 'em all!-程序员宅基地

文章浏览阅读62次。Cut 'em all!题意:求删除了边之后,剩下的每一块联通块他的点数都为偶数,求删除的边最多能是多少。题解:如果n为奇数,直接返回-1,因为不可能成立。如果n为偶数,随意找一个点DFS建树记录下他的子孙+本身的个数。然后再DFS一下,对于每一个点,他的个数为偶数,就把他与父节点的边隔断, cnt++。 最后cnt就是答案。代码: 1 #include<bits/s...

zabbix-agent key属性列表_system.hw.cpu[<cpu>,<info>]-程序员宅基地

文章浏览阅读5.4w次。Key描述返回值参数详细说明agent.hostname返回被监控端名称字符串-返回配置文件中配置的被监控端的名称agent.ping检测被监控端是否存活1 - 运行中 其他 - 未运行-使用函数 nodata()检测客户端是否正在运行_system.hw.cpu[,]

推荐文章

热门文章

相关标签