判断变量是否为空需确保“判得准、兜得住、不误伤”:必须用[ -z "$var" \]加双引号防语法错误和词法展开;用\[ -z "${var+set}" ]区分未设置与空字符串;关键命令须叠加路径校验、白名单或确认机制;posix sh中禁用[[和非标语法,坚持用[和test。

判断变量是否为空,核心是防止空值或未定义变量触发危险操作,比如 rm -rf $path 中 $path 为空时变成 rm -rf,后果严重。关键不是“能不能判”,而是“判得准、兜得住、不误伤”。
用 -z 判断空值,但必须加双引号
标准写法是 [ -z "$var" ]。双引号不是可选项——它防止变量为空时 [ -z ] 变成只有两个参数([ 和 ]),报错 [: -z: unary operator expected;也防止变量含空格、换行或通配符(如 *)被 shell 展开。
-
正确:
if [ -z "$user_input" ]; then echo "拒绝执行"; exit 1; fi -
危险:
if [ -z $user_input ];—— 若$user_input为空,实际执行的是[ -z ],语法错误;若为*a*,可能匹配当前目录文件,导致逻辑错乱
区分“未设置”和“设为空字符串”
业务上常需区别对待:未设置的变量可能是调用遗漏,而空字符串可能是用户明确提交了空值。仅靠 -z 无法分辨两者(两者都返回真)。可靠方式是用参数扩展:
-
[ -z "${var+set}" ]→$var未设置时为真(${var+set}展开为空) -
[ -z "${var:-}" ]→ 先确保变量有值(空字符串或原值),再判空,适合统一处理 - 组合使用:
if [ -z "$var" ] && [ -z "${var+set}" ]; then echo "unset"; elif [ -z "$var" ]; then echo "empty string"; fi
对关键命令做双重防护
不能只靠变量判空就放行危险命令。应叠加路径校验、白名单或交互确认:
- 执行
rm前检查:if [ -n "$target" ] && [ -d "$target" ] && [[ "$target" == /safe/path/* ]]; then rm -r "$target"; fi - 敏感操作加 dry-run 开关:
if [ "$DRY_RUN" = "1" ]; then echo "[DRY] would remove: $target"; else rm -rf "$target"; fi - 删除前强制确认:
[ -n "$target" ] && read -p "Confirm delete $target? (y/N) " -n 1 -r && [[ $REPLY =~ ^[yY]$ ]] && rm -rf "$target"
避免在 POSIX sh 中误用 [[ 和扩展语法
如果脚本声明为 #!/bin/sh 或需兼容 dash、busybox ash,[[、=~、甚至部分参数扩展(如 ${var:+word})可能不可用。此时坚持用 [ -z "$var" ] 和 test 命令,它们是 POSIX 标准,最稳妥。
- 安全写法:
if test -z "$var"; then ...或if [ -z "$var" ]; then ... - 禁用写法:
if [[ -z $var ]](sh下直接报 command not found) - 注意空格:
[ -z"$var" ]缺少空格是语法错误,必须写成[ -z "$var" ]











