[ ]
是 Shell 中用于条件测试的重要结构(也称为 test
命令)。它是 Shell 脚本中进行条件判断的基础工具,虽然看起来简单,但功能非常丰富。
基本概念
[
实际上是一个命令(通常是/usr/bin/[
或 shell 内置命令)]
是[
命令必需的最后一个参数- 命令格式:
[ 表达式 ]
- 表达式结果为真时返回 0,假时返回 1
基本语法
if [ 条件 ]; then
# 条件为真时执行的命令
fi
1. 文件测试
操作符 | 说明 |
---|---|
-e 文件 | 文件是否存在 |
-f 文件 | 是普通文件(非目录/设备文件) |
-d 文件 | 是目录 |
-s 文件 | 文件大小不为空 |
-r 文件 | 文件可读 |
-w 文件 | 文件可写 |
-x 文件 | 文件可执行 |
-L 文件 | 是符号链接 |
-O 文件 | 文件属于当前用户 |
-G 文件 | 文件属于当前用户的组 |
-N 文件 | 文件自上次读取后被修改过 |
文件1 -nt 文件2 | 文件1比文件2新 |
文件1 -ot 文件2 | 文件1比文件2旧 |
示例:
if [ -f "/etc/passwd" ]; then
echo "是一个普通文件"
fi
if [ ! -d "/tmp" ]; then
echo "/tmp 不是目录"
fi
2. 字符串比较
操作符 | 说明 |
---|---|
-z "字符串" | 字符串长度为0 |
-n "字符串" | 字符串长度不为0 |
"串1" = "串2" | 字符串相等 |
"串1" != "串2" | 字符串不相等 |
"串1" < "串2" | 串1在字典序中小于串2 |
"串1" > "串2" | 串1在字典序中大于串2 |
注意:
- 字符串比较操作符两侧必须有空格
- 使用
<
和>
时需要转义(或放在[[ ]]
中)
示例:
if [ "$USER" = "root" ]; then
echo "你是root用户"
fi
if [ -n "$PATH" ]; then
echo "PATH不为空"
fi
3. 数值比较
操作符 | 说明 |
---|---|
num1 -eq num2 | 等于 (equal) |
num1 -ne num2 | 不等于 (not equal) |
num1 -gt num2 | 大于 (greater than) |
num1 -ge num2 | 大于等于 (greater or equal) |
num1 -lt num2 | 小于 (less than) |
num1 -le num2 | 小于等于 (less or equal) |
示例:
if [ "$UID" -eq 0 ]; then
echo "你是超级用户"
fi
if [ "$#" -gt 1 ]; then
echo "参数多于1个"
fi
4. 逻辑运算符
操作符 | 说明 |
---|---|
! 表达式 | 非 |
表达式1 -a 表达式2 | 与 (and) |
表达式1 -o 表达式2 | 或 (or) |
注意:
-a
和-o
已不推荐使用,建议改用&&
和||
(但需要放在[[ ]]
中或分开多个[ ]
)
示例:
if [ -f "$file" -a -r "$file" ]; then
echo "文件存在且可读"
fi
if [ ! -d "$dir" ]; then
echo "不是目录"
fi
5. 复合条件(推荐方式)
更现代的写法是使用多个 [ ]
配合 &&
和 ||
:
if [ -f "$file" ] && [ -r "$file" ]; then
echo "文件存在且可读"
fi
if [ "$age" -lt 18 ] || [ "$age" -gt 65 ]; then
echo "年龄不在18-65之间"
fi
6. 特殊注意事项
-
变量引用要加引号:
if [ -n "$var" ]; then # 正确 if [ -n $var ]; then # 如果$var为空会出错
-
空格是必须的:
if [ "$a" = "$b" ]; then # 正确 if ["$a" = "$b"]; then # 错误
-
字符串与数值比较不要混淆:
if [ "10" -gt "2" ]; then # 数值比较,正确 if [ "10" > "2" ]; then # 字符串比较,可能不是预期结果
7. [ ]
与 [[ ]]
的区别
特性 | [ ] | [[ ]] |
---|---|---|
类型 | 命令 | shell关键字 |
字符串比较 | 需要引号 | 不需要引号 |
模式匹配 | 不支持 | 支持 == 和 =~ |
逻辑运算 | 必须使用 -a 、-o | 可以使用 && 、` |
单词分割 | 会进行 | 不会进行 |
通配符展开 | 会进行 | 不会进行 |
POSIX | 兼容 | 不兼容 |
示例比较:
# [ ] 方式
if [ "$name" = "*.txt" ]; then # 字面比较
if [ -f "$file" -a -r "$file" ]; then
# [[ ]] 方式
if [[ $name == *.txt ]]; then # 模式匹配
if [[ -f $file && -r $file ]]; then
8. 实际应用示例
- 检查参数数量:
if [ $# -ne 2 ]; then
echo "用法: $0 参数1 参数2"
exit 1
fi
- 检查文件是否可执行:
if [ -x "/usr/bin/git" ]; then
echo "Git已安装且可执行"
fi
- 安全的字符串比较:
if [ "${var:-}" = "value" ]; then
echo "var等于value"
fi
- 检查是否是闰年(复杂逻辑示例):
year=2024
if [ $((year % 4)) -eq 0 ] && [ $((year % 100)) -ne 0 ] || [ $((year % 400)) -eq 0 ]; then
echo "$year 是闰年"
fi
总结
[ ]
是 Shell 脚本中最基础的条件测试结构,虽然语法有些古老且严格,但:
- 它是 POSIX 兼容的
- 几乎在所有 Shell 中都能工作
- 是编写可移植脚本的基础