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,
当用户输入数值后,对用户输入的数值进行判断:
- 如果用户输入的值 > 数组a的长度 或者 用户输入的值 < 1,那么就显示 bye并退出循环
- 否则显示用户选择的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[@]}
相关文章:

Linux shell编程学习笔记21:用select in循环语句打造菜单
一、select in循环语句的功能 Linux shell脚本编程提供了select in语句,这是 Shell 独有的一种循环语句,非常适合终端(Terminal)这样的交互场景,它可以根据用户的设置显示出带编号的菜单,用户通过输入不同…...

线性回归与线性拟合的原理、推导与算法实现
关于回归和拟合,从它们的求解过程以及结果来看,两者似乎没有太大差别,事实也的确如此。从本质上说,回归属于数理统计问题,研究解释变量与响应变量之间的关系以及相关性等问题。而拟合是把平面的一系列点,用…...

【C++】set和multiset
文章目录 关联式容器键值对一、set介绍二、set的使用multiset 关联式容器 STL中的部分容器,比如:vector、list、deque、forward_list(C11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元…...

二十、泛型(1)
本章概要 基本概念 与 C 的比较 简单泛型 一个元组类库一个堆栈类RandomList 基本概念 普通的类和方法只能使用特定的类型:基本数据类型或类类型。如果编写的代码需要应用于多种类型,这种严苛的限制对代码的束缚就会很大。 多态是一种面向对象思想的泛…...

【Unity数据交互】游戏中常用到的Json序列化
ˊˊ 👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏࿱…...

TCP的滑动窗口和拥塞控制
目录 滑动窗口 1.发送窗口和接收窗口 2.滑动窗口的分类 停止等待协议:发送窗口大小 1, 接收窗口大小 1 后退N帧协议(GBN):发送窗口大小 > 1,接收窗口大小 1 选择重传协议(SR…...

零信任网络:一种全新的网络安全架构
随着网络技术的不断发展,网络安全问题日益凸显。传统的网络安全策略往往基于信任和验证,但这种信任策略存在一定的局限性。为了解决这一问题,零信任网络作为一种全新的网络安全架构,逐渐受到人们的关注。本文将对零信任网络的概念…...

基于单片机的智能拐杖软件设计
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、整体设计方案2.1本设计设计原理2.1.1单片机基本介绍 二、本设计方案选择三、软件设计AD原理图:原理图…...

小程序如何设置自动预约快递
小程序通过设置自动预约功能,可以实现自动将订单信息发送给快递公司,快递公司可以自动上门取件。下面具体介绍如何设置。 在小程序管理员后台->配送设置处,选择首选配送公司。为了能够支持自动预约快递,请选择正常的快递公司&…...

STM32-HAL库08-TIM的输出比较模式(输出PWM的另一种方式)
STM32-HAL库08-TIM的输出比较模式(输出PWM的另一种方式) 一、所用材料: STM32F103C6T6最小系统板 STM32CUBEMX(HAL库软件) MDK5 示波器或者逻辑分析仪 二、所学内容: 通过定时器TIM的输出比较模式得到预…...

【数据结构】深入浅出讲解计数排序【图文详解,搞懂计数排序这一篇就够了】
计数排序 前言一、计数排序算法核心思路映射 概念补充绝对映射相对映射 二、计数排序算法核心实现步骤三、码源详解四、效率分析(1)时间复杂度 — O(Max(N,range))(2)空间…...

Canvas制作喷泉效果示例
Canvas能制作出很多动画效果,下面是一个制作喷泉效果的示例 效果图 源代码 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <meta name"viewport" content"widthdevice-width, initial-scale1 ,user-…...

什么是NPM(Node Package Manager)?它的作用是什么?
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

oracle如果不适用toad或者plsql工具如何获取索引建表语句
select dbms_lob.substr(dbms_metadata.get_ddl(INDEX,INDEX_NAME,DIXON))||; from dba_indexes where ownerDIXON这个语句可以获取dixon用户的所有索引创建语句,sql脚本形式呈现 点开一个语句查看 如果不使用dbms_lob.substr这个函数最后得到是一个clob selec…...

某大厂伺服驱动器量产方案
本文介一款大厂量产伺服驱动器方案!带2500线省线式编码器,17位增量编码器,20位绝对值编码器!标配CANopen、高精度运动控制,高速总线通讯,主芯片28335FPGA,已验证过,带can和485通讯&a…...

【计算机网络】网络层:数据平面
一.网络层概述 每台路由器的数据平面的主要功能时从其输入链路向其输出链路转发数据报,控制平面的主要功能是协调这些本地的每路由转发动作,使得数据报沿着源和目的地主机之间的路由器路径最终进行端到端传送。 网络层不运行运输层和应用层协议。 转发是…...

Path with “WEB-INF“ or “META-INF“: [webapp/WEB-INF/NewFile.html]
2023-11-04 01:03:14.523 WARN 10896 --- [nio-8072-exec-6] o.s.w.s.r.ResourceHttpRequestHandler : Path with "WEB-INF" or "META-INF": [webapp/WEB-INFNewFile.html] spring.mvc.view.prefix:/webapp/WEB-INF/...
百度OCR 接口调用 提示 216101:param image not exist 问题解决
百度提供的文档并没有描述如何解决,例子也是,用工具请求可以通 axios 请求 需要用FormData 传参 let token await getAccessToken() //官网案例那个 请求token// console.log(token, "token");var formData new FormData();// imageBase64 :Base64 图片数据formD…...
1-10 HTML中input属性
HTML中input属性 text:用于接受单行文本输入password:用于密码输入,输入字符会被掩盖radio:用于单选按钮,用户可以在一组选项中选择一个checkbox:用于复选框,用户可以选择多个选项number&#…...

共焦显微镜使用
x.1 细胞培养 x.2 样品制备 以细菌为例,我们使用荧光染色细菌,静置15分钟。 15分钟后我们使用实验室的专用培养皿,选择吸收100uL的溶液滴在在培养皿中心。 x.3 显微镜使用 我们按照1, 2, 3, 4的顺序打开显微镜, 打开电脑&…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...