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.