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

news2024/11/27 18:49:59

一、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[@]}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Draft-P802.11be-D3.2协议学习__$9-Frame-Format__$9.3.1.22-Trigger-frame-format

Draft-P802.11be-D3.2协议学习__$9-Frame-Format__$9.3.1.22-Trigger-frame-format 9.3.1.22.1 Genreal9.3.1.22.2 Common Info field9.3.1.22.3 Special User Info field9.3.1.22.4 HE variant User Info field9.3.1.22.5 EHT variant User Info field9.3.1.22.6 Basic Trigge…

关于JADX和JEB的小问题

关于JADX和JEB的小问题 很久没水过技术文啦&#xff0c;最近也刚好遇到点小问题&#xff0c;特此记录 第一个问题 在处理app加密逻辑的时候一直拿不到正确的密文&#xff0c;反复看了反编译出来的代码&#xff08;如下图&#xff09; public static string n(String str, Stri…

提升之做事方法

前言&#xff1a;在工作中&#xff0c;做事需要有一套方法&#xff0c;同样的一件事&#xff0c;不同的人去做&#xff0c;就能看到能力的差别&#xff0c;会产生不同的结果。那如何在工作中&#xff0c;提升自己做事的能力&#xff1f; 目录 闭环思维 做事方法论 事前规划 …

网络运维Day03

文章目录 基本命令使用查看文本文件内容-cat命令分页查看文本文件-less命令查看CPU信息-lscpu命令查看系统内核版本-uname命令查看机修改主机名-hostname命令查看IP地址-ifconfig命令创建目录-mkdir命令创建空文件-touch命令查看文件前几行-head命令查看文件后几行-tail命令快速…

2024年CleanMyMac更新了哪些内容?

CleanMyMac作为一款专业的苹果电脑清理软件&#xff0c;它不仅仅能单纯的卸载不用、少用的应用&#xff0c;同时还支持&#xff1a;1、清理应用程序的数据文件&#xff0c;将应用重置回初始状态&#xff0c;减少空间占用&#xff1b;2、自动检查应用更新&#xff0c;保持应用的…

Hyper-V 安装windows10 虚拟机,且能调试窗口大小、与主机之间复制文件

1. 搜索栏--打开‘启动或关闭windows功能’-- 勾选 ‘ Hyper-V ’ 然后点击确定&#xff1b; 2. 搜索栏--打开‘ Hyper-V 快速创建’ ---本地安装源---更改安装源&#xff08;选择 对应的 windows.iso 镜像&#xff09;---创建镜像--启动虚拟机--&#xff08;到达&#xff09;P…

优化|随机零阶优化算法分析

原文&#xff1a;Random Gradient-Free Minimization of Convex Functions. Found Comput Math 17, 527–566 (2017). https://doi.org/10.1007/s10208-015-9296-2 原文作者&#xff1a;Yurii Nesterov, Vladimir Spokoiny 论文解读者&#xff1a;陈宇文 本次知识分享活动挑选…

【中国知名企业高管团队】系列58:创维SKYWORTH

昨天华研荟介绍了位于深圳的彩电三巨头之一——康佳KONKA&#xff0c;今天介绍创维SKYWORTH。两家公司都是以做电视起家的&#xff0c;但是发展历程和现在的业务差别非常大&#xff0c;当然&#xff0c;过程中发生的故事也是波澜起伏。 一、关于创维 创维集团有限公司&#x…

JAVA面经整理(10)

一)MyBatis有什么优缺点&#xff1f; Mybatis是⼀种典型的半自动化的ORM 框架&#xff0c;所谓的半自动&#xff0c;因为还需要⼿动的写 SQL 语句在XML文件里面&#xff0c;再由框架根据SQL以及传入数据来进行组装成要执行的SQL&#xff0c;所谓的ORM框架&#xff0c;就是对象关…

burpsuite进行拦截请求包

当我们进行正常访问浏览器时&#xff0c;进行勾选住如上内容&#xff0c;若我们需要进行拦截某个请求时&#xff0c;首先将如上勾选去掉&#xff0c;然后打开proxy下的Intercept&#xff0c;确保intercept is on 按钮打开。 然后打开intercept is on 按钮即可进行拦截请求

温故知新-Redis01

目录 开场白-追命3连 使用场景 01缓存穿透场景与方案 02布隆过滤器 03缓存击穿场景与方案 04缓存雪崩场景与方案 开场白-追命3连 看你项目中有说用到Redis&#xff0c;都是哪些场景使用了Redis呢&#xff1f; 如果发生了缓存穿透、击穿、雪崩如何应对呢&#xff1f;缓存…

LangChain+LLM实战---ChatGPT的即时插件套件制作

英文原文&#xff1a;Instant Plugins for ChatGPT: Introducing the Wolfram ChatGPT Plugin Kit 在一分钟内构建一个新插件 几周前&#xff0c;我们与OpenAI合作发布了Wolfram插件&#xff0c;使ChatGPT可以使用Wolfram语言和Wolfram|Alpha作为工具&#xff0c;在ChatGPT内部…

Day 6 登录页以及路由(四)Vue页面处理

系列文章目录 本系列记录一下通过Abp搭建后端&#xff0c;VueElement UI Plus搭建前端&#xff0c;实现一个小型项目的过程。 Day 1 Vue 页面框架Day 2 Abp框架下&#xff0c;MySQL数据迁移时&#xff0c;添加表和字段注释Day 3 登录页以及路由 (一&#xff09;Day 4 登录页及…

我终于学会的前端技能——代码调试、打断点

在技术的世界里&#xff0c;要用魔法来打败魔法 说来惭愧我做前端已近三年了竟然还没有学会如何调试代码&#xff0c;也就是给自己的代码打上断点一步步看它的运行状态以达到理清代码运行逻辑、排查问题提升开发效率的目的。直到最近我才学会了这一技能&#xff0c;在这之前我用…

抖音小店参与双十一活动:销售增长的策略与实施

双十一是中国最大的购物狂欢节&#xff0c;对于抖音小店商家来说&#xff0c;参与双十一活动是一个极好的机会&#xff0c;可以在这个繁忙的购物季节中大幅提升销售。下面四川不若与众将介绍一些抖音小店商家如何参与双十一活动的策略和注意事项。 1. 提前准备&#xff1a;在双…

Nginx编译安装和配置

官网:http://nginx.org/ 这里以1.20.2为例 Nginx是C语言写的 如果Linux系统上没有安装C编译环境 先执行下面命令 yum install -y gcc automake autoconf libtool make 如果不确定 可以使用命令查看 命令格式 rpm -q xxx 例如 说明有C编译环境 安装前需要安装4个依赖包…

任正非说:为更好地服务客户,我们把指挥所建到听得到炮声的地方

你好&#xff01;这是华研荟【任正非说】系列的第29篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、产品发展的路标是客户需求导向&#xff0c;企业管理的目标是流程化的组织建设&#xff0c;这两句话归纳了我形容的龙的组织…

海康Visionmaster-全局变量:全局变量关联流程中具体 模块结果的方法

将视觉流程中模板匹配算法模块运行的结果数据&#xff1a;特征匹配点 X 关联全局变量 MatchResultX。 在流程运行的主界面中&#xff0c;按照下面 1&#xff0c;2&#xff0c;3&#xff0c;4 步骤操作&#xff0c;第一步选中算法模块&#xff0c;第二步择模块结果 Tab 页&#…

【NeurIPS 2020】基于蒙特卡罗树搜索的黑箱优化学习搜索空间划分

Learning Search Space Partition for Black-box Optimization using Monte Carlo Tree Search 目标&#xff1a;从采样&#xff08;Dt ∩ ΩA&#xff09;中学习一个边界&#xff0c;从而最大化两方的差异 先使用Kmeans在特征向量上&#xff08; [x, f(x)] &#xff09;聚类…

Python算法例4 求平方根

1. 问题描述 实现int sqrt&#xff08;int x&#xff09;函数&#xff0c;计算并返回x的平方根。 2. 问题示例 sqrt&#xff08;3&#xff09;1&#xff1b;sqrt&#xff08;4&#xff09;2&#xff1b;sqrt&#xff08;5&#xff09;2&#xff1b;sqrt&#xff08;17&#…