Linux shell编程学习笔记21:用select in循环语句打造菜单

一、select in循环语句的功能

Linux shell脚本编程提供了select in语句,这是 Shell 独有的一种循环语句,非常适合终端(Terminal)这样的交互场景,它可以根据用户的设置显示出带编号的菜单,用户通过输入不同的编号就可以选择不同的菜单,并执行与菜单对应的功能,这是C、C++、Java、Python 等编程语言中是没有的。

二、select in循环语句的语法格式

select 变量名 in 值1 [值2 ……值n]
do
    语句或命令1
    [……]
    [语句或命令n]
done

在do 和 done之间,我们可以用if或case语句根据变量名的值执行相应语句或命令,实现不同的功能。

三、实例1

我们会询问你喜欢吃哪种水果,并显示4个水果选项:apple、banana、orrange、peach,以及一个退出循环的选项exit

如果你的选择4个水果中的一个,将会显示你选择的水果名称

如果你选择了是exit,将会看到提示bye,并结束循环。

代码如下:

echo "What is your favourite fruit?"
select f in "apple" "banana"  "orrange" "peach" "exit"
do
    if [[ $f == "exit" ]]; then
        echo "bye"
	break
    else
        echo "You have selected $f"
    fi
 done

(一)在zsh中

# csdn @ edu in ~ [22:32:22] 
$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do; if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple    2) banana   3) orrange  4) peach    5) exit     
?# 1
You have selected apple
?# 4
You have selected peach
?# 5
bye

# csdn @ edu in ~ [22:32:52] 

我们可以看到zsh 根据select in循环语句提供的值显示出了五个菜单项:

1) apple    2) banana   3) orrange  4) peach    5) exit     

每个菜单项前有1个数字。

然后显示提示符 ?# 让我们输入菜单项前的数字来选择相应的菜单项。

我们先输入了1,所以显示You have selected apple

接着我们输入4,所以显示You have selected peach

最后我们输入5,这是退出循环的选项,于是我们看到了bye,并退回到了命令行状态。

(二)在bash中

# csdn @ edu in ~ [22:46:42] 
$ bash
[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do; if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
bash: syntax error near unexpected token `;'
[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple
2) banana
3) orrange
4) peach
5) exit
#? 1 
You have selected apple
#? 3
You have selected orrange
#? 5
bye
[csdn ~]$ 

我们可以看到bash 和zsh 对脚本的支持不太一样。

刚才在zsh中执行正常的脚本,在bash中执行时出错:

bash: syntax error near unexpected token `;'

我们把 do 语句后面的; 去掉后,脚本可以执行了。

根据select in循环语句提供的值显示出了五个菜单项:

我们可以看到bash 像zsh 一样,根据select in循环语句提供的值显示出了五个菜单项:

1) apple
2) banana
3) orrange
4) peach
5) exit 

每个菜单项前有1个数字。

但与zsh的横向显示方式不同,bash采用的是纵向显示方式。

然后显示提示符#?  让我们输入菜单项前的数字来选择相应的菜单项。

bash的这个提示符#?  跟zsh显示的提示符字符顺序是相反的,zsh显示的提示符字符是?#

我们先输入了1,所以显示You have selected apple

接着我们输入3,所以显示You have selected orrange

最后我们输入5,这是退出循环的选项,于是我们看到了bye,并退回到了命令行状态。

四、容错机制测试

在上面的实例1中,如果我们输入的字符不属于菜单项前的数字,代码会怎么执行呢?

(一)在zsh中

# csdn @ edu in ~ [23:03:43] 
$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do; if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?

1) apple    2) banana   3) orrange  4) peach    5) exit     
?# a
You have selected 
?# 6
You have selected 
?# 3
You have selected orrange
?# 5 
bye

# csdn @ edu in ~ [23:04:12] 

 (二)在bash中

# csdn @ edu in ~ [23:04:12] 
$ exec bash
[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do; if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
bash: syntax error near unexpected token `;'
[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple
2) banana
3) orrange
4) peach
5) exit
#? b
You have selected 
#? 9
You have selected 
#? 3
You have selected orrange
#? 5
bye
[csdn ~]$ 

 可以看到,不管zsh还是bash,如果我们输入的字符不属于菜单项前的数字,shell并不会进行干预,代码仍然会执行,并由if语句根据$f的值进行处理。

所以为了实现预期的效果,我们需要自己对用户输入的字符的有效性进行检查和处理。

五、如果 传递给 select in 的值超过9个会怎么显示?(实例2)

我们通过下面的代码,给select in 传递了36个值来测试。

(一) 在 zsh中

# csdn @ edu in ~ [23:14:29] 
$ echo "What is your favourite fruit?"; select f in 1 2 3 4 5 6 7 8  9 a  b c d e f g h i j  k l m n o p q r s t u v w x y z exit; do; if [[ $f == "exit" ]]; then echo "bye"; break; else echo "
You have selected $f"; fi; done
What is your favourite fruit?
1) 1      3) 3      5) 5      7) 7      9) 9      11) b     13) d     15) f     17) h     19) j     21) l     23) n     25) p     27) r     29) t     31) v     33) x     35) z     
2) 2      4) 4      6) 6      8) 8      10) a     12) c     14) e     16) g     18) i     20) k     22) m     24) o     26) q     28) s     30) u     32) w     34) y     36) exit  
?# 1
You have selected 1
?# 18
You have selected i
?# m
You have selected 
?# 36
bye

# csdn @ edu in ~ [23:15:12] 

 

 这次在zsh也是采用纵向多列的方式来显示菜单。 

(二)在bash中

# csdn @ edu in ~ [23:15:12] 
$ exec bash
[csdn ~]$ echo "What is your favourite fruit?"; select f in 1 2 3 4 5 6 7 8  9 a  b c d e f g h i j  k l m n o p q r s t u v w x y z exit; do if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) 1       3) 3      5) 5      7) 7      9) 9     11) b     13) d     15) f     17) h     19) j     21) l     23) n     25) p     27) r     29) t     31) v     33) x     35) z
2) 2       4) 4      6) 6      8) 8     10) a     12) c     14) e     16) g     18) i     20) k     22) m     24) o     26) q     28) s     30) u     32) w     34) y     36) exit
#? 9
You have selected 9
#? 20
You have selected k
#? k
You have selected 
#? 36
bye
[csdn ~]$ 

 

 这次bash显示菜单的方式与zsh一致。

可以看到,当传递给 select in 的值超过9个时,不管zsh还是bash会以10、11……这种方式给值赋予菜单值。

六、利用数组构建容错机制

(一)实例3

我们可以先将要传递给select in 的值定义并存储到一个数组a中,

再把数组a传递给 select in,

当用户输入数值后,对用户输入的数值进行判断:

  1. 如果用户输入的值 > 数组a的长度 或者 用户输入的值 < 1,那么就显示 bye并退出循环
  2. 否则显示用户选择的fruit。

# csdn @ edu in ~ [23:48:42] 
$ a=(apple banana orrange peach);echo "What is your favourite fruit?"; select f in $a; do; if [[ $f -gt ${#a[*]} ]] || [[ $f < 1 ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple    2) banana   3) orrange  4) peach    
?# 1
You have selected apple
?# 4
You have selected peach
?# 0
bye

# csdn @ edu in ~ [23:48:52] 

(二)注意

对于 if [[ $f -gt ${#a[*]} ]] || [[ $f < 1 ]] 

1.如果 将  $f -gt ${#a[*]} 写成 $f > ${#a[*]},代码执行就会出现问题

$f > ${#a[*]}

$ a=(apple banana orrange peach);echo "What is your favourite fruit?"; select f in $a; do; if [[ $f > ${#a[*]} ]] || [[ $f < 1 ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple    2) banana   3) orrange  4) peach    
?# 1
bye

# csdn @ edu in ~ [23:13:38] 

即使我们输入1,代码也会显示bye并跳出循环返回命令行。

这是因为$f 和 ${#a[*]} 在这里进行的是字符串比较。

2.如果将 $f < 1 写为 $f -lt 1,代码执行也会出现问题

# csdn @ edu in ~ [23:48:31] 
$ a=(apple banana orrange peach);echo "What is your favourite fruit?"; select f in $a; do; if [[ $f -gt ${#a[*]} ]] || [[ $f -lt 1 ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done 
What is your favourite fruit?
1) apple    2) banana   3) orrange  4) peach    
?# 1
bye

同样,我们输入1,代码也会显示bye并跳出循环返回命令行。

这是因为$f 和1在进行的是数值比较。

七、如果没有设置退出值(菜单项),如何退出循环?

在上面的实例1和实例2中,我们都设置了exit值给用户选择退出循环,如果我们在脚本中没有作这方面的设置,用户该如何退出循环呢?

有两种方法:

Ctrl+C

Ctrl+D

(一)以bash中用Ctrl+C

# csdn @ edu in ~ [23:26:14] 
$ exec bash
[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do; if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
bash: syntax error near unexpected token `;'
[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple
2) banana
3) orrange
4) peach
5) exit
#? 3
You have selected orrange
#? ^C

按Ctrl+C退出,屏幕上会显示^C。

(二)以bash中用Ctrl+D

[csdn ~]$ echo "What is your favourite fruit?"; select f in "apple" "banana"  "orrange" "peach" "exit"; do if [[ $f == "exit" ]]; then echo "bye"; break; else echo "You have selected $f"; fi; done
What is your favourite fruit?
1) apple
2) banana
3) orrange
4) peach
5) exit
#? 1
You have selected apple
#? 
[csdn ~]$ 

按Ctrl+D退出,屏幕上不会显示出来,更美观一些。 

八、与 case...esac语句配合使用

当我们需要对多个数值分别做不同的处置时,用if语句太麻烦了,我们可以使用case...esca语句配合使用。

我们将实例1修改如下:

a=(apple banana orrange peach)
echo "What is your favourite fruit?"
select f in ${a[*]}
do
   case $f in
     apple) echo 1 apple;;
     banana) echo 2 banana;;
     orrange) echo 3 orrange;;
     peach) echo 4 peach;;
     *) echo bye
        break;;
   esac
done

使用case...esca语句来对用户选择的fruit进行分别处理,如果用户输入的值不在数组a中,将显示bye并退出循环。

(一)在zsh中顺利执行

# csdn @ edu in ~ [22:37:41] 
$ a=(apple banana orrange peach);echo "What is your favourite fruit?"; select f in $a; do; case $f in; apple) echo 1 apple;; banana) echo 2 banana;; orrange)
 echo 3 orrange;;peach) echo 4 peach;; *)echo bye;  break; esac; done

What is your favourite fruit?
1) apple    2) banana   3) orrange  4) peach    
?# 1
1 apple
?# 4
4 peach
?# 5
bye

# csdn @ edu in ~ [22:37:53] 

(二)在bash中

1.命令行执行出错

[csdn ~]$ a=(apple banana orrange peach);echo "What is your favourite fruit?"; select f in $a; do; case $f in; apple) echo 1 apple;; banana) echo 2 banana;; orrange) echo 3 orrange;;peach) echo 4 peach;; *)echo bye;  break; esac; done
bash: syntax error near unexpected token `;'
[csdn ~]$ a=(apple banana orrange peach);echo "What is your favourite fruit?"; select f in $a; do case $f in; apple) echo 1 apple;; banana) echo 2 banana;; orrange) echo 3 orrange;;peach) echo 4 peach;; *)echo bye;  break; esac; done
bash: syntax error near unexpected token `;'
[csdn ~]$ 

bash对;的处理 

 2.创建脚本文件来测试

(1)创建脚本文件a.sh

[csdn ~]$ echo 'a=(apple banana orrange peach)' > a.sh
[csdn ~]$ echo 'echo "What is your favourite fruit?"' >> a.sh
[csdn ~]$ echo 'select f in ${a[*]}' >> a.sh
[csdn ~]$ echo do >> a.sh
[csdn ~]$ echo 'case $f in' >> a.sh
[csdn ~]$ echo 'apple) echo 1 apple;;' >> a.sh
[csdn ~]$ echo 'banana) echo 2 banana;;' >> a.sh
[csdn ~]$ echo 'orrange) echo 3 orrange;;' >> a.sh
[csdn ~]$ echo 'peach) echo 4 peach;;' >> a.sh
[csdn ~]$ echo '*) echo bye' >> a.sh
[csdn ~]$ echo 'break;;' >> a.sh
[csdn ~]$ echo esac >> a.sh
[csdn ~]$ echo done >> a.sh
[csdn ~]$ 

\

(2)查看脚本文件a.sh的内容

[csdn ~]$ cat a.sh
a=(apple banana orrange peach)
echo "What is your favourite fruit?"
select f in ${a[*]}
do
case $f in
apple) echo 1 apple;;
banana) echo 2 banana;;
orrange) echo 3 orrange;;
peach) echo 4 peach;;
*) echo bye
break;;
esac
done
[csdn ~]$ 

(3)执行脚本文件a.sh

[csdn ~]$ . a.sh
What is your favourite fruit?
1) apple
2) banana
3) orrange
4) peach
#? 1
1 apple
#? 3
3 orrange
#? 5
bye
[csdn ~]$ 

注意:

对于数组a=(apple banana orrange peach)'

  • 在zsh中,只需要使用$a 就可以获得所有元素的值
  • 在bash中,使用$a 只能获得第1个元素的值,要获得所有元素的值,需要使用${a[*]}或${a[@]}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/123999.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx-配置拆分(各个模块详细说明)

主配置文件 配置结构 ... #nginx全局块events { #events块... #events块 }http { #http块... #http全局块server { #server块... #server全局块location [PATTERN] { #location块... #location块}location [PATTERN] {...}}serv…

高性能网络编程 - The C10K problem 以及 网络编程技术角度的解决思路

文章目录 C10KC10K的由来C10K问题在技术层面的典型体现C10K问题的本质C10K解决思路思路一&#xff1a;每个进程/线程处理一个连接思路二&#xff1a;每个进程/线程同时处理多个连接&#xff08;IO多路复用&#xff09;● 实现方式1&#xff1a;直接循环处理多个连接● 实现方式…

线上 kafka rebalance 解决

上周末我们服务上线完毕之后发生了一个kafka相关的异常&#xff0c;线上的kafka频繁的rebalance&#xff0c;详细的报错我已经贴到下面&#xff0c;根据字面意思&#xff1a;消费者异常 org.apache.kafka.clients.consumer.CommitFailedException: 无法完成提交&#xff0c;因为…

设计模式-状态模式 golang实现

一 什么是有限状态机 有限状态机&#xff0c;英⽂翻译是 Finite State Machine&#xff0c;缩写为 FSM&#xff0c;简称为状态机。 状态机不是指一台实际机器&#xff0c;而是指一个数学模型。说白了&#xff0c;一般就是指一张状态转换图。 已订单交易为例&#xff1a; 1.…

unity打AB包,AssetBundle预制体与图集(三)

警告&#xff1a; spriteatlasmanager.atlasrequested wasn’t listened to while 条件一&#xff1a;图片打图集里面去了 条件二&#xff1a;然后图集打成AB包了 条件三&#xff1a;UI预制体也打到AB包里面去了 步骤一&#xff1a;先加载了图集 步骤二&#xff1a;再加载UI预…

Spring Cloud LoadBalancer基础知识

LoadBalancer 概念常见的负载均衡策略使用随机选择的负载均衡策略创建随机选择负载均衡器配置 Nacos 权重负载均衡器创建 Nacos 负载均衡器配置 自定义负载均衡器(根据IP哈希策略选择)创建自定义负载均衡器封装自定义负载均衡器配置 缓存 概念 LoadBalancer(负载均衡器)是一种…

jenkins部署job

apt install fontconfig openjdk-11-jre wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.429/jenkins.wardeb包安装 wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.414.3_all.debdpkg -i jenkins_2.414.3_all.deb 访问 http://…

垂直领域大模型落地思考

相比能做很多事&#xff0c;但每件事都马马虎虎的通用大模型&#xff1b;只能做一两件事&#xff0c;但这一两件事都能做好&#xff0c;可被信赖的垂直大模型会更有价值。这样的垂直大模型能帮助我们真正解决问题&#xff0c;提高生产效率。 本文将系统介绍如何做一个垂直领域…

JavaScript脚本操作CSS

脚本化CSS就是使用JavaScript脚本操作CSS&#xff0c;配合HTML5、Ajax、jQuery等技术&#xff0c;可以设计出细腻、逼真的页面特效和交互行为&#xff0c;提升用户体验&#xff0c;如网页对象的显示/隐藏、定位、变形、运动等动态样式。 1、CSS脚本化基础 CSS样式有两种形式&…

学习笔记:CANOE模拟LIN主节点和实际从节点进行通信测试

先写点感想&#xff0c;在LIN开发阶段&#xff0c;我一般用图莫斯USB工具来进行模拟主机节点发送数据。后来公司买了CANOE工具就边学习边搭建了LIN的测试工程&#xff0c;网上的资料真的很少&#xff0c;主要是靠自己一点点摸索前进&#xff0c;总算入门。几个月后的今天&#…

基于swing的人事管理系统

概述 个人项目人事管理系统&#xff0c;针对部门和人员之间的管理。 详细 一、项目UI 二、项目结构 三、项目使用方法 Eclipse导入现有现有项目到工作空间即可&#xff0c;会自动加载包内相关jar包&#xff0c;使用的java源文件 四、部分代码 MainFrm.java package view…

Docker指定容器使用内存

Docker指定容器使用内存 作者&#xff1a;铁乐与猫 如果是还没有生成的容器&#xff0c;你可以从指定镜像生成容器时特意加上 run -m 256m 或 --memory-swap512m来限制。 -m操作指定的是物理内存&#xff0c;还有虚拟交换分区默认也会生成同样的大小&#xff0c;而–memory-…

ubuntu系统黑屏,且光标不闪烁

选择第二个&#xff0c;进入恢复模式 选择第二个&#xff0c;进入恢复模式 选择root 输入&#xff1a; startx然后就可以进入文本界面或者图形化界面了&#xff0c;如果不行&#xff0c;报错&#xff0c;可能需要需要下载这个包&#xff0c;把这个错误到网上搜索一下就可以找…

批量迁移redis实例的key

我们知道migrate 命令可以迁移redis的多个key&#xff0c;但是如果redis的key有非常多&#xff0c;那用起来就很不方便了。 所以下面分享一个脚本来实现批量key的迁移&#xff0c;主要使用的命令为dump和restore 脚本如下&#xff1a; #!/bin/bash redis-cli -h host1 -p 63…

Redis被攻击纪实

一、前言 声明&#xff1a;本文仅供技术交流使用&#xff0c;严禁采用本文的方法进行任何非法活动。 上周新来的同事分享Redis的原理和机制&#xff0c;想起2017年的时候测试环境Redis被攻击&#xff0c;最后只能重新安装服务器&#xff0c;今天试验一把利用Redis漏洞进行攻击…

成集云 | 英克对接零售O2O+线上商城 | 解决方案

方案介绍 零售O2O线上商城是一种新型的商业模式&#xff0c;它通过线上和线下的融合&#xff0c;提供更加便捷的购物体验。其中&#xff0c;O2O指的是线上与线下的结合&#xff0c;通过互联网平台与实体店面的结合&#xff0c;实现线上线下的互动和协同。线上商城则是指通过互…

AI优秀企业案例——机器人流程自动化:达观数据RPA

通过学习业内领先公司的最佳实践&#xff0c;我们可以更好地将它们应用到我们自己的公司和业务中。特别是第三部分&#xff0c;提供了大量应用案例&#xff0c;让我们一起期待看到这些案例的结尾。 1.简介 达观数据是一家专注于智能文本机器人的国家高新技术企业&#xff0c;…

Leetcode-面试题 02.02 返回倒数第 k 个节点

快慢指针&#xff1a;让快指针先移动n个节点&#xff0c;之后快慢指针一起依次向后移动一个结点&#xff0c;等到快指针移动到链表尾时&#xff0c;慢指针则移动到倒数第n个结点位置。 /*** Definition for singly-linked list.* public class ListNode {* int val;* …

矩阵等价和向量组等价的一些问题

什么是向量组&#xff1f;答&#xff1a;向量组是由若干同维数的列向量&#xff08;或同维数的行向量&#xff09;组成的集合。什么是向量组等价&#xff1f;答&#xff1a;两个向量组&#xff0c;各自拼成矩阵A和B&#xff0c;向量组等价就是三秩相等&#xff0c;即r&#xff…

点信息标注_BillboardTextActor3D

开发环境&#xff1a; Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example参考代码 demo解决问题&#xff1a;点附近创建左边或其他信息&#xff0c;且信息面板显示状态不受相机缩放、旋转影响 prj name: BillboardTextActor3D #include…