Sub-comando do comando Bash com variável ambiental

3

Eu tenho esse código no bash

#!/usr/bin/env bash

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

O que eu realmente quero é:

#!/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']")

No entanto, o bash reclama que o CORE_CONFIG não é um comando.

Eu tentei acho que tudo é backticks e, em seguida, aninhamento em várias configurações. Não tem efeito ou 'comando não encontrado'.

Como fazer isso corretamente?

    
por Drachenfels 16.12.2015 / 17:34

4 respostas

4

Uma atribuição só é reconhecida como tal se = for literal e sem aspas, somente em palavras antes do primeiro argumento, e se a parte à esquerda do = formar um nome de variável válido.

Em qualquer outro caso, a palavra é considerada como um argumento de comando ou vários se a divisão de palavras ou globbing gerarem mais (e o primeiro argumento for usado para derivar o comando a ser executado).

Aqui, você poderia fazer:

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

Lá, o conteúdo da variável é passado como um argumento para export e export a trata como uma atribuição env env.

Note que $(...) cria um ambiente de subshell, então essa variável só será exportada para o comando python.

    
por 16.12.2015 / 17:54
1

Ou use o comando env para definir as variáveis de ambiente.

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$ 
    
por 16.12.2015 / 17:46
1

Seu script tem este bloco:

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

Apenas export o valor imediatamente; seu script de shell não se importa, mas passará para o Python quando for chamado.

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
    
por 16.12.2015 / 18:43
0

Do manual de referência do Bash:

If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion.

Então você pode fazer isso:

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