单行 shell 赋值,但仅当变量未设置时(尊重 null 或空值)?

gre*_*emo 3 shell posix

APP_ENV“prod”为DATABASE_DISABLE_MIGRATIONS空时;在任何其他情况下,它应该是true except DATABASE_DISABLE_MIGRATIONS为空或 null。换句话说,必须尊重它的值,并且只有在未设置它时才应进行自动分配。

原来的DATABASE_DISABLE_MIGRATIONS APP_ENV 新的DATABASE_DISABLE_MIGRATIONS
空或空 任何 保留原有价值
非零长度字符串 任何 保留原有价值
未设置 “产品” 空的
未设置 空或不是“prod” “真的”

我正在开始学习 shell (POSIX),并且我已经使用以下代码成功完成了此任务:

#!/bin/sh

if [ "${DATABASE_DISABLE_MIGRATIONS+set}" != set ]; then
    : ${DATABASE_DISABLE_MIGRATIONS:=$( [ "$APP_ENV" = "prod" ] || echo "true" )}
fi

# Just for debug (not meant to be in the single-line assignment of course)
if [ -z "$DATABASE_DISABLE_MIGRATIONS" ]; then
    echo "Empty value, migrations ENABLED"
else
    echo "Not empty value, migrations DISABLED"
fi
Run Code Online (Sandbox Code Playgroud)

可以将上面的代码写成单行语句吗?

当考虑未设置、空或空字符串时,很容易制作单行语句,我经常最终使用:

: ${FOO:=$( [ "$APP_ENV" = "prod" ] || echo "true" )}
Run Code Online (Sandbox Code Playgroud)

变量在未设置、null 或空且不是“prod”时FOO获取值。trueFOOAPP_ENV

也许我缺少类似的“捷径”?

在此输入图像描述

gle*_*man 5

使用 2 个变量的 case 语句可能就是您所追求的:

case "${DATABASE_DISABLE_MIGRATIONS}:${APP}" in
    ?*:* | "":prod) # not empty, or prod
                    echo "Not empty value, migrations DISABLED"
                    ;;
    *) echo "Empty value, migrations ENABLED"
       ;;
esac
Run Code Online (Sandbox Code Playgroud)

虽然这不区分“空”和“未设置”。如果变量值之一包含冒号,也可能会被欺骗。


基于

原来的DATABASE_DISABLE_MIGRATIONS APP_ENV 新的DATABASE_DISABLE_MIGRATIONS
空或空 任何 保留原有价值
非零长度字符串 任何 保留原有价值
未设置 “产品” 空的
未设置 空或不是“prod” “真的”

不将自己限制在 POSIX 上,并且由于“unset”是修改变量的条件,我会:

if [[ ! -v DATABASE_DISABLE_MIGRATIONS ]]; then
    if [[ $APP == prod ]]; then 
        DATABASE_DISABLE_MIGRATIONS=""
    else
        DATABASE_DISABLE_MIGRATIONS=true
    fi
fi
Run Code Online (Sandbox Code Playgroud)

这显然不能满足您的单行愿望,但我认为这是传达您的意图的最易读的方式。


Bod*_*odo 5

命令:

[ -z "${DATABASE_DISABLE_MIGRATIONS+x}" ] && [ "$APP_ENV" != "prod" ] && DATABASE_DISABLE_MIGRATIONS=true
Run Code Online (Sandbox Code Playgroud)

解释:

注释指出将使用此信息检查变量。
[ -z "$DATABASE_DISABLE_MIGRATIONS" ]
信息应该是问题的一部分。

"$DATABASE_DISABLE_MIGRATIONS"除非使用set -u(或),否则对于未设置的变量或空字符串,扩展的结果是相同的set -o nounset,因此可以简化要求。不要用显式的空值替换未设置的变量,以防万一"prod"您可以将其保留为未设置,并且您将获得相同的测试结果。

所以算法可以简化为

  • 如果( DATABASE_DISABLE_MIGRATIONS 未设置且 APP_ENV 不是“prod”)将 DATABASE_DISABLE_MIGRATIONS 设置为“true”
  • (否则什么也不做)

当然,您可以将其写成多行,这将使代码更清晰,但这不是一行,也不会比您在问题中的解决方案短多少。

if [ -z "${DATABASE_DISABLE_MIGRATIONS+x}" ] && [ "$APP_ENV" != "prod" ]
then
    DATABASE_DISABLE_MIGRATIONS=true
fi
Run Code Online (Sandbox Code Playgroud)