単一行シェルの割り当てが、変数が設定されていない場合にのみ該当します(nullまたは空の値を考慮)。

単一行シェルの割り当てが、変数が設定されていない場合にのみ該当します(nullまたは空の値を考慮)。

それ以外の場合は、APP_ENV「prod」は空でなければなりません。DATABASE_DISABLE_MIGRATIONStrue 〜しない限り DATABASE_DISABLE_MIGRATIONS空またはnullです。つまり、価値は尊重されるべきです自動割り当ては、次の場合にのみ発生する必要があります。未設定

オリジナルDATABASE_DISABLE_MIGRATIONS APP_ENV 新しいDATABASE_DISABLE_MIGRATIONS
空または空 どの 元の価値を維持する
長さがゼロ以外の文字列 どの 元の価値を維持する
未設定 「製品」
未設定 空でも「prod」でもない 「本物」

私はシェル(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

上記のコードを1行の文で書くことはできますか?

設定されていない文字列、null、または空の文字列を考慮すると、1行の文を作成するのは簡単です。私はしばしば以下を使用します。

: ${FOO:=$( [ "$APP_ENV" = "prod" ] || echo "true" )}

変数が設定されていない場合は、nullまたは空で、「prod」でない場合はFOO値を取得します。trueFOOAPP_ENV

たぶん似たような「ショートカット」がありませんか?

ここに画像の説明を入力してください。

答え1

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

しかし、これは「空」と「未設定」を区別しません。変数の値の1つにコロンが含まれている場合でも、なりすましの可能性があります。


に基づいて

オリジナルDATABASE_DISABLE_MIGRATIONS APP_ENV 新しいDATABASE_DISABLE_MIGRATIONS
空または空 どの 元の価値を維持する
長さがゼロ以外の文字列 どの 元の価値を維持する
未設定 「製品」
未設定 空でも「prod」でもない 「本物」

自分をPOSIXに制限しないでください。 「未設定」は調整変数を使用するには、次のようにします。

if [[ ! -v DATABASE_DISABLE_MIGRATIONS ]]; then
    if [[ $APP == prod ]]; then 
        DATABASE_DISABLE_MIGRATIONS=""
    else
        DATABASE_DISABLE_MIGRATIONS=true
    fi
fi

これは明らかにあなたの一行の希望を満たしていませんが、あなたの意図を伝える最も読みやすい方法だと思います。

答え2

注文する:

[ -z "${DATABASE_DISABLE_MIGRATIONS+x}" ] && [ "$APP_ENV" != "prod" ] && DATABASE_DISABLE_MIGRATIONS=true

説明する:

コメントこの情報を使用して変数を確認することを示します。
[ -z "$DATABASE_DISABLE_MIGRATIONS" ]
この情報は質問の一部でなければなりません。

"$DATABASE_DISABLE_MIGRATIONS"(または)を使用しない限りset -u、設定されていない変数または空の文字列に対して拡張結果が同じであるため、set -o nounset要件が簡素化されます。設定されていない変数を明示的なnull値に置き換えないでください。"prod"設定しないままにしておくと同じテスト結果が得られるからです。

したがって、アルゴリズムは次のように単純化できます。

  • (DATABASE_DISABLE_MIGRATIONS が設定されておらず、APP_ENV が "prod" でない場合) DATABASE_DISABLE_MIGRATIONS を "true" に設定します。
  • (そうでなければ何もしない)

もちろん、これは複数行で書くことができるので、コードはより明確になりますが、1行ではなく、質問に対する解決策よりはるかに短くはありません。

if [ -z "${DATABASE_DISABLE_MIGRATIONS+x}" ] && [ "$APP_ENV" != "prod" ]
then
    DATABASE_DISABLE_MIGRATIONS=true
fi

答え3

したがって、変数が設定されていない場合はデフォルト値に設定し、それ以外の場合は元の値を維持しますか? (ここではデフォルトは他の変数によって異なりますが、それが気を散らさないようにしましょう。)

もしそうなら、次のようにする方が良いかもしれません。

# don't disable migrations in production by default
if [ "$APP_ENV" = prod ]; then
    default_DATABASE_DISABLE_MIGRATIONS=
else
    default_DATABASE_DISABLE_MIGRATIONS=true
fi
# set default value if unset
if [ "${DATABASE_DISABLE_MIGRATIONS+set}" != set ]; then
    DATABASE_DISABLE_MIGRATIONS=$default_DATABASE_DISABLE_MIGRATIONS
fi

またはより短いもの:

# don't disable migrations in production by default
default_DATABASE_DISABLE_MIGRATIONS=true
if [ "$APP_ENV" = prod ]; then
    default_DATABASE_DISABLE_MIGRATIONS=
fi
# set default value if unset
: "${DATABASE_DISABLE_MIGRATIONS=$default_DATABASE_DISABLE_MIGRATIONS}"

関連する値に基づいたコードゴルフは、他の値に対しても同様のロジックを使用する必要がある場合はコード全体を変更する必要があるため、非生産的なようです。他の同様のケースに適用できる簡単なソリューションを開発することをお勧めします。最後の行は、質問のタイトルで要求されたものとほぼ同じですが、変数が設定されていない場合は、1行のシェル割り当てのみを実行します。 ("${var:=default}"空の値セットにも機能します。)

また、最終的な変数が否定されない場合、読者にとってより明確になる可能性があることも指摘したいと思います。[ -z "$DATABASE_DISABLE_MIGRATIONS" ]デフォルトでは、「移行が無効になっていない場合」などの変数の使用とテストに言及しました。これは「移行が有効になっている場合」と同じです。変数を使用すると簡単に作成できます$DATABASE_ENABLE_MIGRATIONS

答え4

可能:

case ${DATABASE_DISABLE_MIGRATIONS++}:$APP_ENV in
  (:prod) DATABASE_DISABLE_MIGRATIONS=    ;;
  (:*   ) DATABASE_DISABLE_MIGRATIONS=true;;
esac

他のコードと同様に、1行に挿入して行をリンクするか、次のように圧縮することもできます。

case ${DATABASE_DISABLE_MIGRATIONS++}:$APP_ENV in(:prod)DATABASE_DISABLE_MIGRATIONS=;;(:*)DATABASE_DISABLE_MIGRATIONS=true;esac

)しかし私は利点を見ませんでした。

実行とは$(... echo ...)、追加のプロセスを分岐し(ksh93を除く)、コマンドをecho実行し、パイプを介してそのコマンドを送受信することを意味します。これは数十万以上のCPU命令を意味しますが、これらの単純なシェル割り当てとパターンマッチングはわずか数百しかありません。だから私には少し愚かな感じがします。

関連情報