Shell test 命令

《Shell test 命令》深度学习版 🧠

🎉 欢迎来到 Shell 编程中极为关键的一章 —— test 命令。它是 Linux 中用于执行条件判断的“大脑”,是 ifwhilecase 等流程控制语句背后的“逻辑引擎”。掌握它,你就能写出真正智能、自动化的脚本!


🎯 学习目标

  • 理解 test 命令的本质与作用
  • 掌握文件测试、字符串比较、整数比较等各类表达式
  • 能在实际脚本中灵活使用 [ ][[ ]]
  • 学会结合 $?if 实现复杂逻辑判断
  • 避免常见陷阱和语法错误,写出健壮可靠的 Shell 条件语句

⭐ 核心重点(知识点速览)

类型 表达式 含义
文件测试 -f, -d, -r, -w, -x, -e 判断文件是否存在、是否为目录、是否有权限等
字符串测试 =, !=, -z, -n 是否相等、为空、非空
整数测试 -eq, -ne, -gt, -lt, -ge, -le 数值比较
逻辑运算 !, -a, -o&&, `
简写形式 [ expression ] POSIX 兼容方式
扩展形式 [[ expression ]] Bash 扩展,支持更强大语法
返回值 $? 上一个命令的退出状态,0 表示成功/真,非 0 表示失败/假

📖 详细讲解


一、什么是 test 命令?

test 是一个内建命令,用于评估一个表达式是否为真(true)或假(false)。它返回一个退出状态码:

  • 0:表示 true(条件成立)
  • 非0:表示 false(条件不成立)
test 5 -gt 3
echo $?   # 输出 0,说明 5 > 3 成立

💡 通常我们不会直接使用 test,而是使用它的简写形式:[ expression ]


二、文件测试(File Test Operators)

这些操作符用于检查文件或目录的状态。

表达式 描述
-f file 是否为普通文件
-d dir 是否为目录
-r file 是否可读
-w file 是否可写
-x file 是否可执行
-e file 是否存在(不论类型)
-s file 是否存在且大小大于 0

✅ 示例:

file="/etc/passwd"

if [ -f "$file" ]; then
    echo "✅ $file 是一个普通文件"
fi

if [ -r "$file" ]; then
    echo "✅ $file 可读"
fi

if [ -w "$file" ]; then
    echo "✅ $file 可写"
else
    echo "❌ $file 不可写"
fi

三、字符串测试(String Operators)

表达式 描述
str1 = str2str1 == str2 是否相等
str1 != str2 是否不等
-z str 是否为空字符串
-n str 是否非空(注意:变量未赋值时也可能返回 false)

✅ 示例:

name="Alice"

if [ "$name" = "Alice" ]; then
    echo "✅ 用户名正确"
fi

empty=""
if [ -z "$empty" ]; then
    echo "✅ 字符串为空"
fi

⚠️ 注意:

  • 字符串必须用双引号包裹,避免变量未定义时报错。
  • 使用 == 是 Bash 支持的扩展,但为了兼容性建议使用 =

四、整数测试(Integer Operators)

只能用于整数之间的比较,不能用于浮点数。

表达式 描述
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

✅ 示例:

a=10
b=20

if [ $a -gt $b ]; then
    echo "✅ a > b"
elif [ $a -lt $b ]; then
    echo "✅ a < b"
else
    echo "✅ a = b"
fi

五、布尔逻辑运算符(Logical Operators)

运算符 描述 Bash 替代写法
! !
-a &&
-o `

✅ 示例:

age=25

if [ $age -ge 18 -a $age -le 60 ]; then
    echo "✅ 年龄在合法范围内"
fi

# 更推荐使用 [[ ]] 和 && / ||
if [[ $age -ge 18 && $age -le 60 ]]; then
    echo "✅ 年龄在合法范围内"
fi

六、[ ] vs [[ ]]:有什么区别?🔥

特性 [ ] [[ ]]
是否 Bash 内建
是否支持通配符 是(如 =~ 正则匹配)
是否支持 && || 否(需用 -a / -o
是否需要对变量加引号 必须加 推荐加
是否支持字符串模式匹配 是(如 [[ $str == *.log ]]

✅ 示例对比:

str="hello world"

# 使用 [ ]
if [ "$str" = "hello world" ]; then
    echo "✅ 匹配成功"
fi

# 使用 [[ ]]
if [[ $str == "hello world" ]]; then
    echo "✅ 匹配成功"
fi

# 支持通配符匹配
if [[ $str == hello* ]]; then
    echo "✅ 以 hello 开头"
fi

# 支持正则匹配
if [[ $str =~ ^h.*d$ ]]; then
    echo "✅ 符合正则表达式"
fi

七、实战案例分析 🧪

🎯 场景一:备份脚本 + 条件判断

#!/bin/bash

backup_dir="/home/ubuntu/backups"
src_file="/etc/passwd"

if [ ! -d "$backup_dir" ]; then
    mkdir -p "$backup_dir"
    echo "📁 备份目录已创建"
fi

if [ -f "$src_file" ]; then
    cp "$src_file" "$backup_dir/passwd_$(date +%Y%m%d).bak"
    echo "✅ 已备份 passwd 文件"
else
    echo "❌ 错误:源文件不存在"
    exit 1
fi

🎯 场景二:日志清理脚本 + 文件大小判断

logfile="/var/log/app.log"

if [ -f "$logfile" ]; then
    size=$(du -k "$logfile" | awk '{print $1}')
    if [ $size -gt 1024 ]; then   # 如果日志超过 1MB
        echo "🗑️ 日志过大,正在清理..."
        > "$logfile"
    else
        echo "✅ 日志正常,无需清理"
    fi
else
    echo "⚠️ 日志文件不存在"
fi

🎯 场景三:用户登录验证脚本

read -p "请输入用户名:" username
read -sp "请输入密码:" password

valid_user="admin"
valid_pass="123456"

if [ "$username" = "$valid_user" ] && [ "$password" = "$valid_pass" ]; then
    echo -e "\n✅ 登录成功!欢迎 $username"
else
    echo -e "\n❌ 登录失败,请重试"
fi

⚠️ 常见陷阱 & 解决方案

问题 原因 解决方法
[: unary operator expected 变量未赋值或为空 使用双引号 " " 包裹变量
integer expression expected 比较字符串而非整数 使用 -eq 之前确保变量为数字
unexpected operator 使用了 > < 等符号 应使用 -gt -lt
[[ 报错 系统 shell 不是 bash 确保脚本开头为 #!/bin/bash
文件路径含空格 未加引号导致解析错误 始终用双引号包裹路径变量

🧠 总结与小贴士

技巧 说明
test 是 Shell 的“逻辑引擎” 控制脚本走向的核心工具
推荐使用 [[ ]] 更安全、功能更强
始终对变量加双引号 防止未定义或含空格出错
使用 $? 检查结果 调试时非常有用
结合 if, while 构建复杂逻辑 让脚本具备“思考能力”
善用正则匹配和通配符 提升灵活性
避免直接使用 test 命令 推荐使用 [ ][[ ]]

📚 推荐练习题(可选)

  1. 编写一个脚本,判断某个服务(如 nginx)是否运行,如果没有就启动它。
  2. 写一个脚本,检查 /tmp 目录下是否有 .tmp 文件,如果有则删除。
  3. 实现一个简易计算器,接收两个参数和一个运算符(+、-、*、/),输出结果。
  4. 编写一个脚本,判断当前用户是否为 root,不是则提示并退出。
  5. 创建一个日志分析脚本,统计某日志中包含 “error” 的行数。

🎯 下一章预告:《Shell 流程控制 —— if、for、while、until》

你已经掌握了如何进行条件判断,下一步我们将学习如何根据这些判断来控制脚本的执行流程 —— 使用 if, for, while, until 等流程控制语句,让你的脚本真正“动起来”!

需要我继续为你生成下一章内容吗?😊

posted @ 2023-04-02 21:36  红尘过客2022  阅读(41)  评论(0)    收藏  举报