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"
doif [[ $f == "exit" ]]; thenecho "bye"breakelseecho "You have selected $f"fidone

(一)在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[*]}
docase $f inapple) echo 1 apple;;banana) echo 2 banana;;orrange) echo 3 orrange;;peach) echo 4 peach;;*) echo byebreak;;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.rhkb.cn/news/180748.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

七月论文审稿GPT第二版:从Meta Nougat、GPT4审稿到Mistral、LLaMA LongLora

前言 如此前这篇文章《学术论文GPT的源码解读与微调&#xff1a;从chatpaper、gpt_academic到七月论文审稿GPT》中的第三部分所述&#xff0c;对于论文的摘要/总结、对话、翻译、语法检查而言&#xff0c;市面上的学术论文GPT的效果虽暂未有多好&#xff0c;可至少还过得去&am…

vue中的rules表单校验规则使用方法 :rules=“rules“

一、el-form里面必写属性值 :ref"dataForm" // 提交表单时进行校验 :rules"rules" // return 下的校验规则 :model"userForm" // 绑定表单的值 <el-formref"dataForm" // 必写属性值:rules"rules"…

服务器搭建:从零开始创建自己的Spring Boot应用【含登录、注册功能】

当然&#xff0c;你可以先按照IDEA搭建SSM框架【配置类、新手向】完成基础框架的搭建 步骤 1&#xff1a;设计并实现服务器端的用户数据库 在这个示例中&#xff0c;我们将使用MySQL数据库。首先&#xff0c;你需要安装MySQL并创建一个数据库以存储用户信息。以下是一些基本步…

creating server tcp listening socket 127.0.0.1:6379: bind No error

window下启动redis服务报错&#xff1a; creating server tcp listening socket 127.0.0.1:6379: bind No error 解决方案如下按顺序输入如下命令即可连接成功 redis-cli.exeshutdownexit运行&#xff1a;redis-server.exe redis.windows.conf shutdown出现以下错误&#xff…

正点原子嵌入式linux驱动开发——Linux USB驱动

USB是很常用的接口&#xff0c;目前大多数的设备都是USB接口的&#xff0c;比如鼠标、键盘、USB摄像 头等&#xff0c;在实际开发中也常常遇到USB接口的设备&#xff0c;本章就来学习一下如何使能Linux内核自带的USB驱动。这里不会具体学习USB的驱动开发。 USB接口简介 什么是…

2023-11-04 LeetCode每日一题(数组中两个数的最大异或值)

2023-11-04每日一题 一、题目编号 421. 数组中两个数的最大异或值二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数数组 nums &#xff0c;返回 nums[i] XOR nums[j] 的最大运算结果&#xff0c;其中 0 ≤ i ≤ j < n 。 示例 1&#xff1a; 示例 2&…

【笔记】单片机卡死的八大原因和解决方法

在微控制器上&#xff0c;程序卡住&#xff08;即停止执行&#xff09;可能有多种原因。下面我将列举一些常见的原因&#xff0c;并提供一些可能导致程序卡住的示例情况。请注意&#xff0c;这里只是一些示例&#xff0c;并不能穷尽所有可能的情况。 1. 死循环&#xff08;Infi…

Nignx安装负载均衡动静分离以及Linux前端项目部署将域名映射到特定IP地址

目录 一、nginx简介 1.1 定义 1.2 背景 1.3 作用 二、nginx搭载负载均衡提供前后分离后台接口数据 2.1 nginx安装 2.1.1 下载依赖 2.1.2 下载并解压安装包 2.1.3 安装nginx 2.1.4 启动nginx服务 2.2 tomcat负载均衡 2.2.1 负载均衡所需服务器准备 2.2.2 配置修改 …

2022年12月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 列表L1中全是整数&#xff0c;小明想将其中所有奇数都增加1&#xff0c;偶数不变&#xff0c;于是编写了如下图所示的代…

驱动开发11-2 编写SPI驱动程序-点亮数码管

驱动程序 #include <linux/init.h> #include <linux/module.h> #include <linux/spi/spi.h>int m74hc595_probe(struct spi_device *spi) {printk("%s:%d\n",__FILE__,__LINE__);char buf[]{0XF,0X6D};spi_write(spi,buf,sizeof(buf));return 0; …

阿里云推出AI编程工具“通义灵码“;生成式 AI 入门教程 2

&#x1f989; AI新闻 &#x1f680; 阿里云推出AI编程工具"通义灵码"&#xff0c;支持多种语言及实时续写功能 摘要&#xff1a;阿里云推出了一款名为"通义灵码"的AI编程工具&#xff0c;支持多种主流编程语言&#xff0c;包括Java、Python、Go等。该工…

Redis Sentinel 哨兵模式

Sentinel 哨兵模式 Redis Sentinel 官网 Redis 的 Sentinel 文档 -- Redis中国用户组&#xff08;CRUG&#xff09; Sentinel Redis 命令参考&#xff08;红色&#xff09; Sentinel 通过监控的方式获取主机的工作状态是否正常&#xff0c;当主机发生故障时&#xff0c; Senti…

十年JAVA搬砖路——Linux搭建Ldap服务器。

1.安装命令 yum -y install openldap compat-openldap openldap-clients openldap-servers openldap-servers-sql openldap-devel2.启动ldap systemctl start slapd systemctl enable slapd3.修改密码 slappasswd Aa123456获得返回的密码加密密码串&#xff1a; {SSHA}DkSw0…

RPC 原理详解

文章目录 什么是 RPCRPC 基本原理RPC核心功能服务寻址数据编解码网络传输一次RPC的调用过程 实践基于HTTP协议的RPC基于TCP协议的RPC 什么是 RPC RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;即远程过程调用&#xff0c;它允许像调用本地服务一样调用远程服…

Python基础入门例程37-NP37 不低于与不超过(运算符)

最近的博文&#xff1a; Python基础入门例程36-NP36 谁的数字大&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程35-NP35 朋友的年龄是否相等&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程34-NP34 除法与取模运算&#xff08;运算符&#xff09;…

07.Diffusion Model概述

文章目录 Diffusion Model原理Reverse ProcessDenoise模块Forward Process(Diffusion Process) 文字生成图片by Diffusion Model文字生成图像的常见套路Text EncoderFrchet Inception DistanceContrastive Language-Image Pre-Training(CLIP) DecoderGeneration Model 部分截图…

Fourier分析导论——第3章——Fourier级数的收敛性(E.M. Stein R. Shakarchi)

第 3 章 Fourier级数的收敛性(Convergence of Fourier Series) The sine and cosine series, by which one can represent an arbitrary function in a given interval, enjoy among other remarkable properties that of being convergent. This property did not escape…

【Midjourney入门教程1】Midjourney的注册、订阅

文章目录 前言一、Midjourney是什么二、Midjourney注册三、新建自己的服务器四、开通订阅 前言 AI绘画即指人工智能绘画&#xff0c;是一种计算机生成绘画的方式。是AIGC应用领域内的一大分支。 AI绘画主要分为两个部分&#xff0c;一个是对图像的分析与判断&#xff0c;即“…

行业观察:数字化企业需要什么样的数据中心

伴随着数字经济在中国乃至全球的高速发展&#xff0c;数字化转型已经成为广大企业的必经之路。而作为数字经济的核心基础设施&#xff0c;数据中心充当了接收、处理、存储与转发数据流的“中枢大脑”&#xff0c;对驱动数字经济发展和企业数字化转型起到了极为关键的重要作用。…

路由器基础(十一):ACL 配置

访问控制列表 (Access Control List,ACL) 是目前使用最多的访问控制实现技术。访问控制列表是路由器接口的指令列表&#xff0c;用来控制端口进出的数据包。ACL适用于所有的被路由协议&#xff0c;如IP、IPX、AppleTalk 等。访问控制列表可以分为基本访问控制列表和高级访问控制…