shell if(手把手讲解)

Shell if 入门:让脚本学会“判断”与“选择”

你有没有想过,为什么一个简单的 Shell 脚本能根据不同的条件执行不同的操作?比如,检查某个文件是否存在,如果存在就备份,不存在就提示“文件未找到”。这背后的核心逻辑,就是我们今天要深入探讨的——shell if。

Shell if 不是某种语言的专属功能,而是所有 Shell 脚本中实现“条件判断”的基石。它就像你生活中的“决策树”:遇到红灯停,绿灯行;下雨带伞,晴天晒被。Shell if 让脚本不再只是按顺序执行命令,而是能“思考”、能“选择”。

对于初学者来说,掌握 shell if 是迈向自动化脚本的第一步;对中级开发者而言,它是编写健壮、可维护脚本的关键能力。本文将带你从零开始,一步步掌握 shell if 的语法、实战技巧与常见陷阱。


shell if 的基本语法结构

shell if 的基本结构非常清晰,它由 ifelif(else if)、elsefi 组成,其中 fiif 的反写,表示条件块的结束。

if [ 条件判断 ]; then
    # 条件为真时执行的命令
    echo "条件成立,执行这里"
elif [ 另一个条件 ]; then
    # 上一个条件不成立,但这个条件成立时执行
    echo "第一个条件不成立,但第二个条件成立"
else
    # 所有条件都不成立时执行
    echo "所有条件都不成立,走这里"
fi

重点提醒if 后面的 [ 与条件之间必须有空格,[] 之间也必须有空格。这是 Shell 的语法要求,否则会报错。比如 [ -f file.txt ] 正确,[ -ffile.txt ] 错误。

我们来看一个简单的例子,判断用户输入的数字是否大于 10:

#!/bin/bash

echo "请输入一个数字:"
read num

if [ $num -gt 10 ]; then
    echo "你输入的数字大于 10"
elif [ $num -eq 10 ]; then
    echo "你输入的数字等于 10"
else
    echo "你输入的数字小于 10"
fi
  • read num:从用户输入读取数据并存入变量 num
  • [ $num -gt 10 ]:判断 num 是否大于 10。-gt 是“greater than”的缩写。
  • elif 用于处理多个条件,逻辑清晰。
  • fi 必不可少,否则脚本会报语法错误。

常见条件判断操作符详解

在 shell if 中,条件判断依赖于一组操作符,它们分为几类:数值比较、字符串比较、文件测试等。掌握这些操作符,才能写出准确的判断逻辑。

数值比较操作符

操作符 含义 示例
-eq 等于 [ $a -eq $b ]
-ne 不等于 [ $a -ne $b ]
-gt 大于 [ $a -gt $b ]
-ge 大于等于 [ $a -ge $b ]
-lt 小于 [ $a -lt $b ]
-le 小于等于 [ $a -le $b ]

注意:这些操作符只能用于整数比较。如果变量是小数或字符串,会出错。

字符串比较操作符

操作符 含义 示例
= 字符串相等 [ "$str1" = "$str2" ]
!= 字符串不相等 [ "$str1" != "$str2" ]
-z 字符串为空 [ -z "$str" ]
-n 字符串非空 [ -n "$str" ]

重要提示:字符串比较时,建议用双引号包裹变量,防止变量为空时报错。

#!/bin/bash

echo "请输入用户名:"
read username

if [ -z "$username" ]; then
    echo "用户名不能为空!"
elif [ "$username" = "admin" ]; then
    echo "欢迎管理员登录"
else
    echo "欢迎用户 $username"
fi

文件测试操作符

操作符 含义 示例
-f 是否为普通文件 [ -f "file.txt" ]
-d 是否为目录 [ -d "/home" ]
-r 是否可读 [ -r "file.txt" ]
-w 是否可写 [ -w "file.txt" ]
-x 是否可执行 [ -x "script.sh" ]

这些操作符在自动化脚本中非常实用,比如备份前检查源文件是否存在。


实战案例:编写一个备份脚本

让我们用 shell if 实现一个真实场景:一个自动备份脚本。它会检查源文件是否存在,如果存在就备份到目标目录,否则提示错误。

#!/bin/bash

SOURCE_FILE="/home/user/data.txt"
BACKUP_DIR="/backup"

if [ -f "$SOURCE_FILE" ]; then
    echo "✅ 源文件存在,开始备份..."
    
    # 检查备份目录是否存在,不存在则创建
    if [ ! -d "$BACKUP_DIR" ]; then
        echo "📁 备份目录不存在,正在创建..."
        mkdir -p "$BACKUP_DIR"
    fi

    # 执行备份
    cp "$SOURCE_FILE" "$BACKUP_DIR/"
    echo "✅ 备份成功,文件已保存至 $BACKUP_DIR"

else
    echo "❌ 错误:源文件 $SOURCE_FILE 不存在!"
    exit 1  # 退出脚本并返回错误码
fi
  • [ -f "$SOURCE_FILE" ]:判断文件是否存在。
  • ! -d "$BACKUP_DIR"! 表示“非”,即目录不存在时为真。
  • mkdir -p:创建目录,-p 保证父目录也存在。
  • exit 1:脚本执行失败时返回非零退出码,便于其他脚本或任务调度器识别。

这个例子展示了 shell if 的嵌套使用,逻辑清晰,可读性强。


常见陷阱与最佳实践

即使掌握了语法,初学者也容易踩坑。以下是几个高频错误和应对建议。

陷阱 1:变量未加引号

if [ $var -eq 10 ]; then

if [ "$var" -eq 10 ]; then

如果 $var 为空,[ $var -eq 10 ] 会变成 [ -eq 10 ],导致语法错误。加双引号能避免这个问题。

陷阱 2:使用 == 进行字符串比较

[ ] 中,== 并不是合法的比较符。你应该用 =。虽然有些 Shell(如 bash)支持 ==,但为了兼容性,建议统一使用 =

陷阱 3:忘记 fi

这是最常见的语法错误。if 必须配对 fi,否则脚本会报错。

最佳实践建议

  • 所有变量都用双引号包裹,如 "$var"
  • 使用 [[ ]] 替代 [ ](适用于 bash),支持更复杂的判断,如正则匹配。
  • 多层判断时使用 elif,避免冗余的 if 嵌套。
  • 为脚本添加注释,提升可维护性。

进阶技巧:使用 [[ ]] 提升判断能力

[[ ]] 是 bash 提供的扩展语法,比 [ ] 更强大。它支持模式匹配、正则表达式等高级功能。

#!/bin/bash

filename="document.pdf"

if [[ "$filename" =~ ^[a-zA-Z]+\.pdf$ ]]; then
    echo "文件名符合 PDF 格式"
else
    echo "文件名格式不正确"
fi

if [[ "hello world" == h* ]]; then
    echo "以 h 开头"
fi
  • =~ 用于正则匹配。
  • h* 表示以 h 开头的字符串。
  • [[ ]] 不需要空格分隔,语法更灵活。

虽然 [[ ]] 不是 POSIX 标准,但在大多数 Linux 系统中都可用,推荐在 bash 脚本中使用。


结语:shell if 是自动化脚本的“大脑”

shell if 不仅是一个语法结构,更是脚本“智能”的起点。它让你的脚本不再只是“死板执行”,而是能根据环境、输入、状态做出响应。

从判断文件是否存在,到控制程序流程,再到实现复杂的自动化任务,shell if 都扮演着核心角色。掌握它,意味着你已经迈入了 Shell 脚本开发的进阶之路。

无论你是想写一个简单的系统检查脚本,还是构建一个完整的部署流程,shell if 都是你不可或缺的工具。多写、多试、多调试,你会发现,原来“判断”这件事,也可以如此优雅而强大。