使用未设置的变量有什么危害吗?

IQA*_*eas 7 shell bash environment-variables

假设我有以下代码:

# Check if the color prompt is enabled and supported on this system
if [ -n "$force_color_prompt" ] && [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    GREEN="\033[1;32m"
    DIM="\033[2m"
    RESET="\033[00m"
fi

echo -e "Oh, ${GREEN}green${RESET} world, ${DIM}don't desert me now...${RESET}"
Run Code Online (Sandbox Code Playgroud)

如果启用颜色支持,它将呼出一条漂亮的彩色线条。如果未启用颜色支持,则不会${GREEN}设置类似值,文本将以通常的黑色背景白色打印出来。

代码依赖于这样一个事实,即未设置的变量只会计算为空字符串(在我的测试中,它们确实如此)。这会在某些系统上导致错误或问题,还是所有不存在的变量总是评估为空字符串?有什么理由我不应该依赖这个机制吗?

god*_*eek 8

不存在的变量在扩展为$FOOor (等效地)时将始终评估为空字符串${FOO},并且依赖于它没有害处,除非在一种特殊情况下:

如果有人set -u在您尝试使用该变量之前调用了当前 shell,则他们已启用此设置:

              -u 执行参数时将未设置的变量视为错误
                      等扩张。如果在未设置时尝试扩展
                      变量,shell 会打印一条错误消息,如果没有
                      交互式,以非零状态退出。

这意味着,如果您正在编写一个函数,该函数被设计为由其他人控制的脚本,则您可能需要对使用未设置的变量保持警惕 - 否则,如果它们set -u在调用您的函数之前使用过,则它们的脚本第一次尝试扩展未设置的变量时会退出并显示错误消息。

如果您正在编写自己的脚本,那么指望将未设置的变量扩展为空字符串是没有害处的。

编辑- 另外,只是一个想法 - 由于您将整个事情取决于终端是否可以使用 terminfo 颜色功能,为什么不实际使用 terminfo 来生成序列,而不是对 vt100 值进行硬编码?就像是:

if [ -n "$force_color_prompt" ] && type tput &>/dev/null; then
    GREEN="$(tput setaf 2)$(tput bold)"
    DIM="$(tput dim)"
    RESET="$(tput sgr0)"
fi
Run Code Online (Sandbox Code Playgroud)

这可能会让您在其他终端之间获得一些可移植性(尽管不可否认,不使用您显示的代码的终端数量很少并且正在减少)。它也可能会失去一些可移植性,因为根据 terminfo 定义的正确程度,某些平台上可能不存在某些功能。天啊。