Skip to content

一、为什么会有单双括号的混淆? ​

在编写 Shell 自动化脚本或排查 CI 流水线异常时,很多工程师常遇到以下诡异的报错:

text
[: =: unary operator expected
[: too many arguments
syntax error in conditional expression

甚至更严重的事故是:在判断数值大小时使用了 [ $a > $b ],结果并没有做比较,反而在当前目录下创建了一个名为 $b 的空文件,并将原本的数据直接清空重定向了。

产生这些问题的根本原因在于:没有真正理解 单括号 [ ] 与 双括号 [[ ]] 在 Linux 内核与 Shell 解释器中的底层机制差异。


二、单括号 [ ](test 命令的语法糖) ​

在 Linux 中,[ 并不是一个纯符号,而是一个实际存在的内置命令(等同于 /usr/bin/test):

bash
type [
# 输出:[ is a shell builtin

既然是命令,就必须严格遵守命令行传参规则:

  1. 必须严格留空格:[ 之后与 ] 之前必须有空格分隔,否则 Shell 会将其视作一个未知的命令名(如 ["$a");
  2. 变量必须加双引号包装:
    bash
    # 🔴 危险写法:如果变量 $status 为空,会被展开为 [ = "success" ],报 unary operator expected
    if [ $status = "success" ]; then ... fi
    
    # ✅ 规范写法:展开后保持为空字符串参数 [ "" = "success" ]
    if [ "$status" = "success" ]; then ... fi
  3. 复合逻辑使用 -a 与 -o:
    bash
    if [ "$a" = "1" -a "$b" = "2" ]; then ... fi
  4. 大于小于号必须转义:因为未转义的 > 和 < 会被 Shell 当作重定向符号解析,必须写成 \> 和 \<。

三、双括号 [[ ]](现代 Bash 复合关键字,强烈推荐) ​

[[ ]] 是 Bash 等现代 Shell 的内置关键字(Keyword),它不是独立命令,具有更智能、更容错的词法解析能力:

bash
type [[
# 输出:[[ is a shell keyword

核心优势与增强特性: ​

  1. 防止空变量参数爆炸:即使变量为空且未加双引号,Bash 关键字也能安全识别,不会触发语法崩溃:
    bash
    if [[ $status == "success" ]]; then ... fi # 安全有效
  2. 直接支持现代逻辑运算符:可直接使用 &&(与)、||(或)、!(非),彻底告别晦涩的 -a / -o:
    bash
    if [[ "$status" == "RUNNING" && $retry_count -lt 5 ]]; then ... fi
  3. 大小比较无需转义:可以直接书写 > 和 < 进行字符排序比较,绝不会误触发文件重定向;
  4. 原生支持通配符与正则表达式匹配(=~):
    bash
    # 1. 通配符模式匹配(右侧无需加引号)
    if [[ "$filename" == *.tar.gz ]]; then
        echo "检测到归档压缩包"
    fi
    
    # 2. 强大的正则匹配(=~)
    if [[ "$user_input" =~ ^[0-9]+$ ]]; then
        echo "输入为纯数字序列"
    fi

四、生产常用条件测试参数速查 ​

在日常运维与测试自动化中,最常用的单目条件判断操作符:

参数检查对象为真(True)的条件典型场景
-f文件类型目标路径存在且为普通文件检查安装包、配置文件是否存在
-d目录类型目标路径存在且为目录检查部署目录、日志挂载点
-s文件状态目标文件存在且大小大于 0 字节检查生成的报表是否为空文件
-z字符串字符串长度为 0(为空)校验必填入参是否缺省
-n字符串字符串长度不为 0(非空)校验环境变量是否已配置
-x权限目标文件存在且具备可执行权限检查二进制脚本是否有 +x 权限
bash
# 规范的工程级前置检查示例:
target_conf="/opt/app/configs/app.yaml"

if [[ ! -f "$target_conf" || ! -s "$target_conf" ]]; then
    echo "[ERROR] 目标配置文件不存在或文件内容为空: $target_conf" >&2
    exit 1
fi

测试开发工程师 · 专注自动化与系统架构 | 邮箱: hansblog@atumsoul.win