Skip to content

Bash 条件语句 if/elif/else 用法指南

问题描述

许多初学者在使用 Bash 的条件语句时遇到困难,特别是字符串比较的场景。一个常见的错误示例如下:

bash
aaa="xxx"
if [[ $aaa -eq "bbb" ]]; then
   echo "bbb"
elif [[ $aaa -eq "ccc" ]]; then
   echo "ccc"
else
   echo "something else"
fi

这段代码总是输出 bbb,无论变量 aaa 的值是什么。这主要是因为使用了错误的比较操作符和引号处理方式。

解决方案

使用正确的比较操作符

在 Bash 中,-eq 是用于数值比较的操作符,而不是字符串比较。对于字符串比较,应该使用 ===

重要提示

-eq 只能用于数字比较,使用它进行字符串比较会导致意外的结果

正确使用引号

在比较字符串时,应该使用引号包裹变量,以防止字段分割和其他 shell 扩展问题。

修复后的代码

bash
aaa="xxx"
if [[ "$aaa" == "bbb" ]]; then
   echo "bbb"
elif [[ "$aaa" == "ccc" ]]; then
   echo "ccc"
else
   echo "something else"
fi

使用 case 语句作为替代方案

对于多个条件判断,case 语句通常是更好的选择,代码更简洁清晰:

bash
case "$aaa" in
    "bbb") echo "bbb";;
    "ccc") echo "ccc";;
    *) echo "something else";;
esac

详细解释

比较操作符的区别

bash
# 使用 -eq, -ne, -lt, -gt 等进行数值比较
num=10
if [ $num -eq 10 ]; then
    echo "数字等于10"
fi
bash
# 使用 ==, =, != 进行字符串比较
str="hello"
if [ "$str" == "hello" ]; then
    echo "字符串匹配"
fi

引号的重要性

在 shell 脚本中,变量扩展时使用引号是防止意外行为的关键最佳实践:

bash
# 错误的写法 - 可能导致字段分割和通配符扩展
if [ $aaa = "bbb" ]; then

# 正确的写法 - 使用引号保护变量
if [ "$aaa" = "bbb" ]; then

潜在问题

如果不使用引号,当变量值为空或包含空格时,条件语句会出错

不同括号类型的区别

Bash 支持多种条件测试语法:

  • 单括号 [ ]: POSIX 兼容,较老的语法
  • 双括号 [[ ]]: Bash 扩展,提供更多功能,如模式匹配
  • 双圆括号 (( )): 用于算术运算

最佳实践总结

  1. 字符串比较使用 ===,不要使用 -eq
  2. 始终用引号包裹变量,防止字段分割
  3. 优先使用 [[ ]],它比 [ ] 更安全且功能更多
  4. 多条件判断考虑使用 case 语句,代码更清晰
  5. 保持代码一致性,在整个脚本中使用相同的条件语法

完整示例

bash
#!/bin/bash

# 获取用户输入或使用默认值
input="${1:-default}"

# 使用 if/elif/else 结构
if [[ "$input" == "start" ]]; then
    echo "正在启动服务..."
elif [[ "$input" == "stop" ]]; then
    echo "正在停止服务..."
elif [[ "$input" == "status" ]]; then
    echo "查看服务状态..."
else
    echo "未知命令: $input"
    echo "可用命令: start, stop, status"
fi

# 使用 case 语句的等价实现
case "$input" in
    "start") echo "正在启动服务...";;
    "stop") echo "正在停止服务...";;
    "status") echo "查看服务状态...";;
    *) echo "未知命令: $input"
       echo "可用命令: start, stop, status";;
esac

通过遵循这些最佳实践,你可以避免常见的 Bash 条件语句陷阱,编写出更加健壮和可读的 shell 脚本。