環境変数を使用した Bash コマンドの置換

環境変数を使用した Bash コマンドの置換

bashにこのコードがあります

#!/usr/bin/env bash

DB_NAME=$(CORE_CONFIG=core.config.core_test python -c "from core import config; print config.DATABASE['db_name']")

私が本当に欲しいものは:

#!/usr/bin/env bash

ENV_VARIABLE="CORE_CONFIG=core.config.core_test"

DB_NAME=$($ENV_VARIABLE python -c "from core import config; print config.DATABASE['db_name']")

しかし、bashはCORE_CONFIGがコマンドではないと文句を言います。

私はすべてをバックティックして、さまざまな構成でネストしようとしたと思います。効果がないか、「コマンドが見つかりません」。

正しいことは何ですか?

答え1

=代入はリテラルで、引用符がない場合は、最初の引数の前の単語でのみ認識され、=左側の部分が有効な変数名を形成する場合にのみ認識されます。

場合によっては、単語がコマンド引数として扱われるか、単語の分割やグロービングによってより多くのコマンドが生成される場合は、複数のコマンド引数として処理されます(最初の引数は、実行するコマンドを派生させるために使用されます)。

ここでは、次のことができます。

DB_NAME=$(
  export "$ENV_VARIABLE"
  python...
)

ここで変数の内容は引数として渡され、export環境export変数の代入として扱われます。

$(...)変数がpythonコマンドでのみエクスポートされるように、サブシェル環境が作成されます。

答え2

または、envコマンドを使用して環境変数を設定します。

bash-4.1$ env_foo="xxx=a xxxx=b"
bash-4.1$ env $env_foo perl -E 'say "$_=$ENV{$_}" for grep /^xx/, keys %ENV'
xxx=a
xxxx=b
bash-4.1$ (echo '#!/bin/bash'; history 3 | head -2 | perl -anE 'shift @F; say "@F"') > a_script
bahs-4.1$ 

答え3

スクリプトには次のブロックがあります。

if [ "$1" = "1" ]; then
    ENV_PREFIX=""
elif [ "$1" = "2" ]; then
    ENV_PREFIX="export CORE_CONFIG=core.config.config_api_test"
elif [ "$1" = "3" ]; then
    ENV_PREFIX="export CORE_CONFIG=core.config.config_nosetest"
else
    echo "Unrecognised mode, options are 1 - default environment, 2 - api test, 3 - nosetest)"
    exit 1
fi

即時export価値;シェルスクリプトはこれを気にしませんが、呼び出されるとPythonに渡されます。

if [ "$1" = "1" ]; then
    :  # Do nothing
elif [ "$1" = "2" ]; then
    export CORE_CONFIG="core.config.config_api_test"
elif [ "$1" = "3" ]; then
    export CORE_CONFIG="core.config.config_nosetest"
else
    echo "Unrecognised mode, options are 1 - default environment, 2 - api test, 3 - nosetest)"
    exit 1
fi

DB_PORT=5432
DB_USER=$(
    python -c "from core import config; print config.DATABASE['user']"
)
DB_NAME=$(
    python -c "from core import config; print config.DATABASE['db_name']"
)
DB_PASS=$(
    python -c "from core import config; print config.DATABASE['password']"
)
DB_HOST=$(
    python -c "from core import config; print config.DATABASE['host']"
)

unset CORE_CONFIG   # Optional

答え4

Bashリファレンスマニュアルから:

パラメーターの最初の文字が感嘆符(!)の場合、1段階変数間接指定が導入されます。 Bash は、残りの引数で構成される変数値を変数名として使用します。次に、その変数を展開し、引数自体の値ではなく、残りの置換にその値を使用します。これを間接拡張といいます。

だからあなたはこれを行うことができます:

DB_NAME=$(${!ENV_VARIABLE} python -c "from core import config; print config.DATABASE['db_name']")

関連情報