Qual é a maneira mais simples de script para verificar se uma variável de shell é exportada?


20

Para algumas sessões de shell, desejo poder imprimir um sinalizador de aviso se uma variável de shell não for definida e exportada.

É bastante simples fazer algo assim para imprimir "Erro" no prompt, se SET_MEnão estiver definido ou nulo.

test_var () { test -z "$1" && echo Error; }
PS1='$(test_var "$SET_ME") \$ '

No entanto, isso falha ao sinalizar se eu definir SET_MEsem exportá-lo, o que é um erro que desejo detectar. $(bash -c 'test -z "$SET_ME" && echo Error;')Exceto por algo parecido ou com saudação na saída export, existe uma verificação simples que posso fazer para testar se SET_MEfoi exportada?

Uma solução não-POSIX, somente bash, é completamente aceitável.

Respostas:


11

Use o declarecomando e o operador de correspondência de expressão regular:

test_var () {
    # $1 - name of a shell variable
    var=$1
    [[ -z "${!var}" ]] && echo Error
    [[ $(declare -p $1)  =~ ^declare\ -[aAilrtu]*x[aAilrtu]*\  ]] || echo Error
}

Eu acho que é isso que estou procurando. Em teoria, o re talvez precise ser mais flexível, por exemplo, se eu tivesse uma variável exportada somente leitura, mas na prática nunca uso outros typesetatributos.
perfil completo de CB Bailey

Bom ponto. Vou consertar para a posteridade.
18712 chepner

Parece que tentar citar a expressão regular impede que ela funcione como uma expressão regular em bash> = 3.2.
CB Bailey

Também há uma inconsistência, -z "$1"assume que eu estou passando o valor de uma variável para test_var(como eu estava) enquanto declare -pespera seu nome. Eu vim com este teste, que leva o nome de uma variável de shell: test_exported_notnull () { re='^declare -\w*x'; [[ -n $(eval echo \$$1) ]] && [[ $(declare -p "$1") =~ $re ]]; }.
perfil completo de CB Bailey

Para evitar isso eval, basta adicionar esta primeira linha: e var=$1, em seguida, use [[ -z "${!var}" ]] && echo Error.
Chepner

4

Sei que a pergunta tem 3 anos, no entanto, pode-se encontrar a seguinte solução mais simples:

[ "$(bash -c 'echo ${variable}')" ]

respostas, se a variável for exportada e tiver um valor não vazio.


4

No Bash 4.4 ou posterior , você pode usar a ${parameter@a} expansão de parâmetros do shell para obter uma lista de atributos sobre um parâmetro, incluindo se ele é exportado.

Aqui está uma função simples demonstrativa ${parameter@a}, que informa se uma determinada variável é exportada, devido ao seu nome:

function is_exported {
    local name="$1"
    if [[ "${!name@a}" == *x* ]]; then
        echo "Yes - '$name' is exported."
    else
        echo "No - '$name' is not exported."
    fi
}

Exemplo de uso:

$ is_exported PATH
Yes - 'PATH' is exported.
$ foo=1 is_exported foo
Yes - 'abc' is exported.
$ bar=1; is_exported bar
No - 'abc' is not exported.
$ export baz=1; is_exported baz
Yes - 'baz' is exported.
$ export -n baz; is_exported baz
No - 'baz' is not exported.
$ declare -x qux=3; is_exported qux
Yes - 'qux' is exported.

Como funciona:

O formato retornado por ${parameter@a}é um caractere por atributo, com o significado de cada caractere de atributo vindo das opções correspondentes do comando declare - neste caso, queremos procurar x- exportado.


Melhor resposta se você estiver usando o Bash 4.4 ou mais recente!
Andy

3

Você pode usar compgencom sua -Xopção para determinar se uma variável é exportada:

compgen -e -X "!$MAY_BE_EXPORTED_VARIABLE"

Por exemplo:

$ NOT_EXPORTED="xxx"
$ compgen -e -X '!SHELL'
SHELL
$ compgen -e -X '!NOT_EXPORTED'
$ echo $?
1

Melhor resposta compatível! Mais do que duas vezes mais lento que a solução $ {parameter @ a}, mas muito mais compatível para casos do bash 3.2
Andy

2

Se eu me resignar a ter que usar exporte grep, o teste mais simples provavelmente será algo assim.

export | grep -Eq '^declare -x SET_ME='

ou se eu quiser não nulo também:

export | grep -Eq '^declare -x SET_ME=".+"'

11
O POSIX 7 diz que exportnão é especificado e define um formato preciso para export -psimilar ao bash, exportmas diferente. Mas o bash parece ignorar o POSIX e usa o mesmo formato que exportpara export -p!
Ciro Santilli # 16/14

1

O exportcomando, fornecido sem parâmetros, fornece uma lista de nomes exportados no ambiente atual:

$ FOO1=test
$ FOO2=test
$ export | grep FOO
$ export FOO2
$ export | grep FOO
declare -x FOO2="test"

Alguns cortes e sedações se livram do cotão:

export | cut -d' ' -f 3- | sed s/=.*//

Aqui está sua lista de exportações, pronta para processamento adicional.


11
Isso funciona, mas eu estava esperando uma resposta mais leve com menos garfos implícitos (portanto, "menos que [...] cumpra a saída de export"), pois meu uso planejado é rápido.
CB Bailey

@CharlesBailey: Entendo. Cheguei a isso pesquisando na página de manual do bash export, e essa foi a única coisa que me veio à cabeça. Nenhuma ajuda do shell também escapa. O exportestá embutido de qualquer maneira, mas duvido que você possa evitar o grep.
DevSolar

1

O método mais simples em que posso pensar atualmente:

[ bash -c ': ${v1?}' 2>/dev/null ]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.