Shell脚本实战:10个高频面试题解析与避坑指南(附完整代码)

Shell脚本实战:10个高频面试题解析与避坑指南(附完整代码)

最近几年,无论是面试Linux运维、SRE还是DevOps工程师,Shell脚本能力几乎成了必考项。我作为面试官,看过太多候选人因为一些看似基础实则暗藏玄机的脚本问题而失分。更常见的情况是,候选人能写出“能跑”的脚本,但代码里充满了潜在的“坑”,比如无法处理带空格的文件名、错误处理机制缺失,或者性能上存在明显短板。这篇文章,我想从一个面试官和一线工程师的双重角度,和你聊聊那些高频出现的Shell脚本面试题。我不会仅仅给你一个标准答案,而是会拆解每一道题背后的考察意图,指出常见的错误写法,并提供一个经过生产环境检验、更健壮、更优雅的解决方案。希望这些内容能帮你不仅通过面试,更能写出真正可靠的脚本。

1. 变量与字符串处理:从“能用”到“可靠”的跨越

变量操作是Shell脚本的基石,但很多开发者在这里就埋下了隐患。面试中,关于变量引用、字符串比较和参数传递的问题,往往是为了考察你对Shell执行模型的理解深度。

一个典型的初级错误是直接使用未加引号的变量进行文件操作。比如,面试官可能会让你写一个重命名脚本。你可能会写出这样的代码:

for file in *.txt; do
    mv $file ${file%.txt}.log
done

这段代码在大多数情况下能工作,但一旦遇到名为 my file.txt 的文件,就会彻底失败。因为 $file 展开后变成了两个词 myfile.txtmv 命令会接收到错误的参数数量。正确的做法是始终用双引号包裹变量引用,尤其是在路径和文件名操作中:

for file in *.txt; do
    mv "$file" "${file%.txt}.log"
done

这里有个更隐蔽的坑:如果当前目录没有 .txt 文件,*.txt 会保持原样,for 循环会执行一次,file 的值就是字面量的 *.txt。为了避免这种情况,可以设置 nullglob 选项:

shopt -s nullglob
for file in *.txt; do
    mv "$file" "${file%.txt}.log"
done

关于字符串比较,很多人习惯使用 =,但在 [ ] 测试中,等号两边必须留有空格。更推荐使用双中括号 [[ ]],它在Bash中更安全,能自动处理变量中的空格,并且支持正则匹配:

# 传统写法,容易因空格出错
if [ "$name" = "John" ]; then
    echo "Hello John"
fi

# 更健壮的现代写法
if [[ $name == "John" ]]; then
    echo "Hello John"
fi

# 使用正则表达式匹配
if [[ $filename =~ \.txt$ ]]; then
    echo "这是一个文本文件"
fi

注意:[[ ]] 是Bash的扩展语法,虽然现在绝大多数环境都支持,但如果你需要编写高度可移植的、符合POSIX标准的脚本,仍需使用 [ ]

下表总结了变量处理中的关键要点和常见陷阱:

场景 危险写法 安全写法 原因解析
文件操作 rm $file rm "$file" 防止单词拆分,正确处理带空格的文件名
字符串比较 [ $var = "test" ] [[ $var == "test" ]] 避免变量为空时报语法错误,更清晰的语法
命令替换 `cmd` $(cmd) 更好的嵌套支持,更易读
默认值设置 echo $name echo ${name:-"Guest"} 提供变量未定义时的默认值,防止空输出
数组迭代 for i in ${array[@]} for i in "${array[@]}" 保留数组元素中的空格

2. 条件判断与流程控制:避免逻辑漏洞

条件判断是脚本逻辑的核心,但 ifcase 语句中的细节常常被忽略。面试官让你写一个判断文件是否存在的脚本,可能是在考察你对测试运算符的熟悉程度,以及是否考虑到了边缘情况。

先看一个看似正确但有问题的基础示例:

if [ -f $FILE_PATH ]; then
    echo "文件存在"
else
    echo "文件不存在"
fi

如果 FILE_PATH 变量未设置或为空,这个测试会变成 [ -f ],这会被解释为测试 -f 这个字符串是否非空,结果永远为真!正确的做法是:

if [[ -n "$FILE_PATH" ]] && [[ -f "$FILE_PATH" ]]; then
    echo "文件存在且路径有效"
else
    echo "文件不存在或路径为空"
fi

对于数值比较,新手常犯的错误是使用数学比较符 >< 而不是 -gt-lt。在单中括号 [ ] 中,前者表示重定向,会导致语法错误:

count=10
# 错误写法:会被解释为重定向
if [ $count > 5 ]; then
    echo "大于5"
fi

# 正确写法
if [ $count -gt 5 ]; then
    echo "大于5"
fi

# 双括号中的数学比较(推荐用于数值)
if (( count > 5 )); then
    echo "大于5"
fi

case 语句在匹配模式时非常高效,比一连串的 if-elif 更清晰。但要注意它的匹配模式是通配符风格,不是正则表达式:

read -p "输入操作 (start/stop/restart/status): " action

case $action in
    start|s)
        echo "启动服务..."
        # 启动命令
        ;;
    stop|p)
        echo "停止服务..."
        # 停止命令
        ;;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值