- 文档
- 教程
- DevOps
- 运维
【免费下载链接】devops-exercises
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
导读
本篇技术指南围绕 devops-exercises 仓库 Shell 脚本练习中的Sum(求和)题目展开,这是仓库中专门用于训练Bash 函数(Functions)这一主题的基础级练习。通过本文,你将掌握如何编写一个接受两个命令行参数、用正则表达式校验输入合法性、再通过自定义函数完成算术运算的完整 Bash 脚本,并了解仓库内其他 Shell 练习(如 Number of Arguments、Factors)所体现的 Bash 最佳实践,可直接用于日常自动化脚本开发与面试准备。
一、练习背景:题目要求与约束
Sum 练习位于仓库的 topics/shell/sum.md,对应的完整参考答案见 topics/shell/solutions/sum.md。在 topics/shell/README.md 的练习总表中,它被明确归类为:
- 主题(Topic):Functions(函数)
- 难度:Basic(基础)
题目目标(Objectives)
- 编写一个脚本,接收两个数字并打印它们的和;
- 确保输入有效(即确实从用户那里得到了两个数字);
- 通过运行脚本并传入两个数字作为参数来测试它。
约束(Constraints)
- 必须使用函数(Use functions)。
这是一道典型的“参数解析 + 输入校验 + 函数封装”组合题,麻雀虽小五脏俱全:它同时考察了 Bash 的位置参数($1、$2)、正则匹配(=~)、条件判断(if)、算术展开($(( )))以及函数定义与调用——这些都是日常 Shell 脚本中最常用的能力。
二、参考答案逐行拆解
题目要求使用函数,参考答案(topics/shell/solutions/sum.md)给出了一个完整可运行的脚本:
#!/usr/bin/env bash re='^[0-9]+$' if ! [[ $1 =~ $re && $2 =~ $re ]]; then echo "Oh no...I need two numbers" exit 2 fi function sum { echo $(( $1 + $2 )) } sum $1 $21. Shebang:#!/usr/bin/env bash
第一行使用#!/usr/bin/env bash而非硬编码的#!/bin/bash。env会在当前用户的PATH中查找bash,这提高了脚本在不同 Linux 发行版(bash 可能安装在/usr/bin、/bin或其他位置)之间的可移植性,是仓库内几乎所有练习脚本统一采用的写法(参见 topics/shell/solutions/hello_world.md 等)。
2. 定义正则:re='^[0-9]+$'
re='^[0-9]+$'这里定义了一个扩展正则表达式(ERE):
^锚定字符串开头;[0-9]匹配一个十进制数字字符;+表示前面的数字至少出现一次;$锚定字符串结尾。
因此该模式只匹配“完全由一位或多位数字组成”的字符串,例如5、42、1024合法,而abc、3.14、-7、12x都不匹配。这一校验写法在 topics/shell/README.md 的“如何检查给定参数是否为数字”自测题中也有对应体现:regex='^[0-9]+$'。
注意:
-7不会被判定为合法数字,因为-不在字符类[0-9]中。这是本题校验策略的一个边界,下文“改进方向”会专门讨论。
3. 输入校验:[[ $1 =~ $re && $2 =~ $re ]]
if ! [[ $1 =~ $re && $2 =~ $re ]]; then echo "Oh no...I need two numbers" exit 2 fi这是整个脚本的“安全门”:
[[ ... ]]是 Bash 的扩展条件测试结构,其中=~运算符用于正则匹配(右侧为正则模式,左侧为被测试字符串);&&在[[ ]]内部表示逻辑与,要求$1和$2同时都是纯数字才通过校验;!对整个条件取反:只要有一个参数不是数字,条件即成立,进入错误分支;- 打印提示信息
Oh no...I need two numbers后以退出码2结束脚本。
为什么用退出码 2?在 Unix/Linux 惯例中,退出码0表示成功,非零表示失败,而用具体的非零值区分错误类型是常见做法(例如1表示一般性错误、2表示参数或用法错误)。这里exit 2与许多标准命令行工具“用法错误返回 2”的约定一致,便于调用方在脚本或 CI 中根据退出码判断失败原因。仓库中 topics/shell/solutions/num_of_args.md 的参考答案也采用了类似的思路——参数数量不合法时return 1。
另外一个值得注意的细节:[[ $1 =~ $re ]]中$1没有加双引号。在[[ ]]内部这是安全的,因为[[ ]]不会做词法分割与路径名展开;但=~右侧的模式变量$re一旦被加引号就会变成字面量匹配(即把字符串^[0-9]+$当普通文本去比对),这是 Bash 正则匹配最容易踩的坑。本题通过把模式存入变量再引用,恰好规避了这个问题。
4. 定义函数:function sum { ... }
function sum { echo $(( $1 + $2 )) }function sum是 Bash 中定义函数的两种语法之一(另一种是sum() { ... },两者等价);- 函数体内的
$1、$2是函数的参数,而不是脚本的参数——调用sum $1 $2时,脚本的$1、$2会被“传参”给函数,函数内通过自身的$1、$2读取。这正是题目要求“使用函数”时函数与脚本参数分离的关键点; $(( ... ))是 Bash 的算术展开(Arithmetic Expansion),$(( $1 + $2 ))会先做整数加法,再把结果作为字符串展开;echo把计算结果打印到标准输出。
关于算术运算,topics/shell/README.md 的自测部分也给出了两种实现方式:$(( 1 + 2 ))和expr 1 + 2。参考答案选择了前者,因为它是 Bash 内建特性,无需启动外部进程,性能更好、语法更简洁。
5. 调用函数:sum $1 $2
脚本末尾调用函数,并把脚本的两个位置参数传入。此时函数内部计算$1 + $2并echo结果,脚本退出码为最后一个命令(echo)的退出码,即0(成功)。
三、完整运行与测试步骤
把参考答案保存为sum.sh后,按以下步骤在终端验证:
# 1. 赋予可执行权限 chmod +x sum.sh # 2. 正常用例:传入两个数字 ./sum.sh 3 5 # 输出:8 # 3. 大数字用例 ./sum.sh 100 200 # 输出:300 # 4. 非法输入:参数不是数字 ./sum.sh abc def # 输出:Oh no...I need two numbers # 退出码为 2(可通过 echo $? 查看) # 5. 非法输入:只传一个数字 ./sum.sh 3 # 输出:Oh no...I need two numbers($2 为空,空串不匹配正则)题目目标第 3 条要求“运行脚本并传入两个数字作为参数进行测试”,以上用例完整覆盖了“合法输入”与“非法输入”两条路径。可以用echo $?验证:合法路径退出码为0,非法路径退出码为2,这说明脚本的校验逻辑真实生效。
四、从仓库其他练习看 Bash 最佳实践
Sum 练习虽然只有 15 行,但把它与仓库内同目录的其他 Shell 练习参考答案对照,可以提炼出一整套可复用的 Bash 工程化习惯:
1. 用set -eu提升脚本健壮性
topics/shell/solutions/num_of_args.md 的参考答案开头是:
#!/usr/bin/env bash set -eu main() { case $# in 0) printf "%s" "Usage: ./<program name> <argument>"; return 1 ;; 1) printf "%s" "Got it: $1"; return 0 ;; *) return 1 ;; esac } main "$@"其中set -eu的含义是:-e让脚本在任一命令失败时立即退出,-u让脚本在引用未定义变量时直接报错。这与 topics/shell/README.md 自测题中“用set -e让 Bash 在特定命令失败时退出”的回答相互印证。它还展示了两个优秀习惯:
- 把主逻辑封装进
main()函数,再用main "$@"显式传入所有参数——"$@"是参数数组,"$*"是单个字符串,两者差异在 README 自测部分有专门解释; - 用
case $#处理“零个 / 一个 / 多个参数”的分支,这与 Sum 脚本用exit 2表达用法错误的理念一脉相承。
如果把这一习惯移植到 Sum 脚本,可以写成set -u(配合$1直接引用时未传参会产生告警,此时正则校验分支恰好会拦截空参数),不过参考答案刻意保持最小化,只聚焦“函数 + 校验”两个考点。
2. 用(( ))做整数判断
topics/shell/solutions/factors.md 展示了另一条算术展开的用法:
#!/usr/bin/env bash (( $1 % 2 )) || res="one factor" (( $1 % 3 )) || res+="...actually two!" echo ${res:-$1}(( ))是 Bash 的算术求值结构,表达式结果为0时返回退出码 1(假),非0时返回退出码 0(真),配合||可以实现紧凑的条件赋值;${res:-$1}则是参数展开的默认值语法(变量为空时用$1兜底)。这与 Sum 脚本中的$(( $1 + $2 ))同属算术展开家族,区别仅在于前者用于判断、后者用于计算。
3. 条件表达式的两种风格
topics/shell/solutions/argument_check.md 用一行实现了 if/else 的简写(Bash 中的“三元运算符”风格):
[[ ${1} == "pizza" ]] && echo "with pineapple?" || echo "I want pizza!"而 Sum 脚本使用完整的多行if ! [[ ... ]]; then ... fi。两种风格各有适用场景:简单分支用&&/||更简洁,涉及exit、多语句或可读性优先时用完整if更清晰——本题因为有校验失败退出逻辑,参考答案选择了后者,是合理的取舍。
4. 交互式输入的替代方案
如果题目“从用户那里得到两个数字”不是指命令行参数,而是运行时输入,则可以使用read关键字(topics/shell/README.md 自测题:read x会等待用户输入并存入变量x)。topics/shell/solutions/count_chars.md 的while read line; do ... done就是交互式读取的完整示例。但本题明确要求“传递两个数字作为参数”(Objectives 第 3 条),因此参考答案采用$1/$2参数方案。
五、常见陷阱与扩展改进方向
理解了参考答案后,可以沿着几个方向继续深挖,这也是面试中常见的追问点:
负数与小数不支持:
^[0-9]+$只能匹配非负整数。若需支持负数,可改为^-?[0-9]+$;若需支持小数或科学计数法,则需要更复杂的模式(如^-?[0-9]+(\.[0-9]+)?$),且$(( ))本身只支持整数运算,浮点需要改用awk、bc或printf等工具。参数缺失时的表现:脚本要求两个参数,但若用户只传一个参数(如
./sum.sh 3),$2为空串,正则匹配失败,脚本会走错误分支——行为是安全的。但若要给出更精确的提示(区分“参数数量不足”和“参数非数字”),可参考 topics/shell/solutions/num_of_args.md 先用$#检查参数个数,再做格式校验。引用与引号:在
[[ =~ ]]中右侧正则若被加引号会失去正则语义;在[ ](POSIX test)中则没有=~可用。日常调试时可以用bash -x sum.sh 3 5打开执行跟踪(topics/shell/README.md 自测部分明确推荐-x参数调试 Bash 脚本),观察每个命令的实际展开结果。函数返回值与退出码:函数内
echo输出到 stdout 是“返回计算结果”的常用手段;若函数需要表达“计算失败”,可以用return 非零并让调用方检查$?。参考 topics/shell/solutions/num_of_args.md 中main()对return 1/return 0的用法。
小结
Sum 是 devops-exercises 仓库 Shell 练习集中最精简、最聚焦的一道函数练习:它用 15 行代码串联起了 Shebang、正则校验、条件分支、算术展开、函数定义与调用、退出码六大 Bash 核心知识点。结合仓库中 topics/shell/solutions/num_of_args.md、topics/shell/solutions/factors.md、topics/shell/solutions/argument_check.md 等参考答案以及 topics/shell/README.md 的自测问答,你可以把这一小脚本扩展成一套稳定的“参数校验 + 函数封装 + 错误处理”模板,直接复用到日志清理、批量计算、部署脚本等真实运维场景中。
- 文档
- 教程
- DevOps
- 运维
【免费下载链接】devops-exercises
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
相关推荐
devops-exercises 实战:用 Bash 函数与参数校验编写一个可靠的求和脚本
devops exercises 实战:用 Bash 函数与参数校验编写一个可靠的求和脚本 导读 本文以 devops exercises 仓库中的 sum.m
文档教程DevOps运维devops-exercises 的 Bash 参数数量检查实战:用 case 语句编写健壮的 CLI 参数校验脚本
devops exercises 的 Bash 参数数量检查实战:用 case 语句编写健壮的 CLI 参数校验脚本 导读 本指南围绕 devops exerc
文档教程DevOps运维devops-exercises 实战:用 Bash 编写主机存活检测脚本(host_status / It's Alive!)
devops exercises 实战:用 Bash 编写主机存活检测脚本(host_status / It's Alive!) 本指南以 devops exe
文档教程DevOps运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考