Eu tenho alguns scripts shell do Unix nos quais preciso verificar se certas variáveis de ambiente estão definidas antes de começar a fazer as coisas, então faço esse tipo de coisa:
if [ -z "$STATE" ]; then
echo "Need to set STATE"
exit 1
fi
if [ -z "$DEST" ]; then
echo "Need to set DEST"
exit 1
fi
que é muita digitação. Existe um idioma mais elegante para verificar se um conjunto de variáveis de ambiente está definido?
Edição: devo mencionar que essas variáveis não têm valor padrão significativo - o script deve errar se houver algum não definido.
Respostas:
Expansão de parâmetros
A resposta óbvia é usar uma das formas especiais de expansão de parâmetros:
Ou melhor (consulte a seção 'Posição das aspas duplas' abaixo):
A primeira variante (usando just
?
) requer que STATE seja definido, mas STATE = "" (uma sequência vazia) está OK - não exatamente o que você deseja, mas a notação alternativa e antiga.A segunda variante (usando
:?
) requer que DEST seja definido e não esteja vazio.Se você não fornecer nenhuma mensagem, o shell fornecerá uma mensagem padrão.
A
${var?}
construção é portátil de volta à Versão 7 UNIX e ao Bourne Shell (1978 ou nos próximos anos). A${var:?}
construção é um pouco mais recente: acho que estava no System III UNIX por volta de 1981, mas pode ter sido no PWB UNIX antes disso. Está, portanto, no Korn Shell e nos shells POSIX, incluindo especificamente o Bash.Geralmente é documentado na página de manual do shell em uma seção chamada Expansão de parâmetros . Por exemplo, o
bash
manual diz:O comando do cólon
Provavelmente devo acrescentar que o comando dois pontos simplesmente tem seus argumentos avaliados e depois é bem-sucedido. É a notação de comentário do shell original (antes de '
#
' até o final da linha). Por um longo tempo, os scripts de shell Bourne tiveram dois pontos como o primeiro caractere. O Shell C leria um script e usaria o primeiro caractere para determinar se era para o Shell C (um#
hash ' ') ou o shell Bourne (:
dois pontos ' '). Então o kernel entrou em ação e adicionou suporte aos comentários '#!/path/to/program
' e o shell Bourne recebeu '#
', e a convenção do cólon foi esquecida. Mas se você encontrar um script que comece com dois pontos, agora saberá o porquê.Posição de aspas duplas
blong perguntou em um comentário :
A essência da discussão é:
A resposta curta é "faça o que
shellcheck
sugere":Para ilustrar o motivo, estude o seguinte. Observe que o
:
comando não ecoa seus argumentos (mas o shell avalia os argumentos). Queremos ver os argumentos, portanto, o código abaixo usaprintf "%s\n"
no lugar de:
.Observe como o valor em
$x
é expandido para primeiro*
e depois para uma lista de nomes de arquivos quando a expressão geral não está entre aspas duplas. Isto é o queshellcheck
está recomendando que deve ser corrigido. Não verifiquei que ela não se opõe ao formulário em que a expressão está entre aspas duplas, mas é uma suposição razoável de que estaria tudo bem.fonte
if [ "$variable" = "abc" ]; then : OK; else : variable is not set correctly; fi
.Tente o seguinte:
fonte
[ -z "$STATE" ] && { echo "Need to set STATE"; exit 1; }
veja esta publicação no blogSua pergunta depende do shell que você está usando.
A casca de Bourne deixa muito pouco no que você procura.
MAS...
Funciona, em quase todos os lugares.
Apenas tente ficar longe do csh. Foi bom para os sinos e assobios que adicionou, comparou a concha Bourne, mas está realmente rangendo agora. Se você não acredita em mim, tente separar o STDERR no csh! (-:
Existem duas possibilidades aqui. O exemplo acima, ou seja, usando:
pela primeira vez, você precisa se referir a $ MyVariable. Isso leva o env. var MyVariable e, se não estiver definido no momento, atribui o valor de SomeDefault à variável para uso posterior.
Você também tem a possibilidade de:
que apenas substitui SomeDefault pela variável em que você está usando essa construção. Ele não atribui o valor SomeDefault à variável, e o valor de MyVariable ainda será nulo depois que essa instrução for encontrada.
fonte
Certamente, a abordagem mais simples é adicionar a
-u
opção ao shebang (a linha na parte superior do seu script), supondo que você esteja usandobash
:#!/bin/sh -u
Isso fará com que o script saia se houver alguma variável não acoplada oculta.
fonte
Se
MyVariable
for definido e não nulo, redefinirá o valor da variável (= nada acontece).Senão,
MyVariable
está definido comoSomeDefault
.O acima tentará executar
${MyVariable}
, portanto, se você quiser apenas definir a variável, faça:fonte
Na minha opinião, a verificação mais simples e mais compatível para #! / Bin / sh é:
Novamente, isso é para / bin / sh e também é compatível com sistemas Solaris antigos.
fonte
/bin/sh
que apoiar a${var:?}
notação, etc.unset MYVAR
eMYVAR=
.foo
não estiver definido,"$foo"
ainda será expandido para a sequência vazia.bash
4.2 introduziu o-v
operador que testa se um nome está definido com algum valor, mesmo a string vazia.fonte
Eu sempre usei:
Receio que não seja muito mais conciso.
Sob CSH, você tem $? STATE.
fonte
STATE
está vazio ou não definido, não apenas não definido.Para futuras pessoas como eu, eu queria dar um passo adiante e parametrizar o nome do var, para que eu possa percorrer uma lista de nomes de variáveis com tamanho variável:
fonte
Podemos escrever uma boa asserção para verificar várias variáveis de uma só vez:
Chamada de amostra:
Resultado:
Mais afirmações aqui: https://github.com/codeforester/base/blob/master/lib/assertions.sh
fonte
Isso também pode ser uma maneira:
http://unstableme.blogspot.com/2007/02/checks-whether-envvar-is-set-or-not.html
fonte
Nenhuma das soluções acima funcionou para meus propósitos, em parte porque verifiquei o ambiente em busca de uma lista aberta de variáveis que precisam ser definidas antes de iniciar um processo demorado. Eu acabei com isso:
fonte
Em vez de usar scripts de shell externos, costumo carregar funções no meu shell de login. Eu uso algo como isso como uma função auxiliar para verificar as variáveis de ambiente em vez de qualquer variável definida:
fonte
is_this_an_env_variable P
retornará sucesso porquePATH
existe.A
$?
sintaxe é bem organizada:fonte
$?
é o status de saída do comando anterior;$?BLAH
é a sequência que consiste no status de saída do comando anterior concatenado com 'BLAH'. Isso não testa a variável$BLAH
. (Há um rumor que poderia fazer mais ou menos o que é necessário nocsh
, mas conchas são deixadas à beira do mar.)