if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens
210
Nota para quem procura uma solução: Existem muitas respostas altamente classificadas para esta pergunta que respondem à pergunta "é variável não vazia". As mais soluções de correção ("conjunto de variáveis") são mencionadas nas respostas de Jens e Lionel abaixo.
Nathan Kidd
8
Russell Harmon e Seamus também estão corretos em seus -vtestes, embora isso pareça estar disponível apenas em novas versões bashe não portável em conchas.
Graeme
5
Conforme apontado por @NathanKidd, as soluções corretas são fornecidas por Lionel e Jens. prosseek, você deve mudar sua resposta aceita para uma delas.
Garrett
3
... ou a resposta incorreta pode ter o voto negativo dos mais exigentes entre nós, já que @prosseek não está resolvendo o problema.
Jul3
Respostas:
2305
(Normalmente) O caminho certo
if[-z ${var+x}];then echo "var is unset";else echo "var is set to '$var'";fi
onde ${var+x}é uma expansão de parâmetro que avalia como nada se não varestiver definida e substitui a string de xoutra forma.
Cotação Digressão
As aspas podem ser omitidas (é o que podemos dizer em ${var+x}vez de "${var+x}"), porque essa sintaxe e uso garantem que isso só será expandido para algo que não requer aspas (uma vez que se expande para x(que não contém quebras de palavras e não precisa de aspas) ou para nada (que resulta em [ -z ], que avalia convenientemente o mesmo valor (verdadeiro) que [ -z "" ]também)).
No entanto, embora as aspas possam ser omitidas com segurança, e isso não foi imediatamente óbvio para todos (nem sequer ficou claro para o primeiro autor desta explicação de citações que também é um dos principais codificadores do Bash), às vezes seria melhor escrever a solução entre aspas [ -z "${var+x}" ], pelo menor custo possível de uma penalidade de velocidade O (1). O primeiro autor também adicionou isso como um comentário ao lado do código usando esta solução, fornecendo o URL para esta resposta, que agora também inclui a explicação de por que as aspas podem ser omitidas com segurança.
(Muitas vezes) O caminho errado
if[-z "$var"];then echo "var is blank";else echo "var is set to '$var'";fi
Isso geralmente está errado porque não faz distinção entre uma variável que está desconfigurada e uma variável que está configurada para a cadeia vazia. Ou seja, se var='', então, a solução acima produzirá "var is blank".
A distinção entre não definido e "definido para a cadeia vazia" é essencial em situações em que o usuário precisa especificar uma extensão ou lista adicional de propriedades, e que não a especificação dos padrões é um valor não vazio, enquanto a cadeia vazia deve ser especificada. faça com que o script use uma extensão vazia ou uma lista de propriedades adicionais.
A distinção pode não ser essencial em todos os cenários. Nesses casos [ -z "$var" ], tudo ficará bem.
@Garrett, sua edição fez esta resposta incorreta, ${var+x}é a substituição correta a ser usada. Usar [ -z ${var:+x} ]não produz resultados diferentes de [ -z "$var" ].
Graeme
11
Isso não funciona. Estou recebendo "não definido", independentemente de var ser definido como um valor ou não (limpo com "unset var", "echo $ var" não produz saída).
Brent212 9/09/14
10
Para a sintaxe da solução $ {parameter + word}, a seção do manual oficial é gnu.org/software/bash/manual/… ; no entanto, um erro nisso, ele não menciona muito claramente essa sintaxe, mas diz apenas citar (omitir os dois pontos [":"] resulta em um teste apenas para um parâmetro não definido. .. $ {parameter: + word} [significa] Se o parâmetro for nulo ou não definido, nada será substituído; caso contrário, a expansão da palavra será substituída.); a referência citada pubs.opengroup.org/onlinepubs/9699919799/utilities/… (é bom saber) tem documentos muito mais claros aqui.
Destino Architect
7
Parece que aspas são necessárias quando você usa várias expressões, por exemplo, [ -z "" -a -z ${var+x} ]entra bash: [: argument expectedno bash 4.3-ubuntu (mas não, por exemplo, zsh). Eu realmente não gosto da resposta usando uma sintaxe que funciona em alguns casos.
FauxFaux
41
Usar um simples [ -z $var ]não é mais "errado" do que omitir aspas. De qualquer forma, você está fazendo suposições sobre sua entrada. Se você está bem tratando uma string vazia como não definida, [ -z $var ]é tudo o que precisa.
Nshew 5/05
910
Para verificar a variável de sequência não nula / diferente de zero, ou seja, se configurada, use
if[-n "$1"]
É o oposto de -z. Eu me pego usando -nmais de -z.
Você usaria como:
if[-n "$1"];then
echo "You supplied the first parameter!"else
echo "First parameter not supplied."fi
Normalmente, prefiro o [[ ]]excesso [ ], pois [[ ]]é mais poderoso e causa menos problemas em determinadas situações (veja esta pergunta para obter uma explicação da diferença entre os dois). A pergunta pede especificamente uma solução bash e não menciona nenhum requisito de portabilidade.
Fluxo
18
A questão é como se pode ver se uma variável está definida . Então você não pode assumir que a variável está definida.
hellogoodbye
7
Concordo, []funciona melhor especialmente para scripts shell (não bash).
Hengjie
73
Falha set -u.
Ciro Santilli escreveu
63
Observe que esse -né o teste padrão, de forma mais simples [ "$1" ]ou também [[ $1 ]]funciona. Observe também que a [[ ]]citação é desnecessária .
tne
478
Veja como testar se um parâmetro está desmarcado ou vazio ("Nulo") ou definido com um valor :
+--------------------+----------------------+-----------------+-----------------+|Expression| parameter | parameter | parameter ||in script:|Set and NotNull|SetButNull|Unset|+--------------------+----------------------+-----------------+-----------------+| ${parameter:-word}| substitute parameter | substitute word | substitute word || ${parameter-word}| substitute parameter | substitute null | substitute word || ${parameter:=word}| substitute parameter | assign word | assign word || ${parameter=word}| substitute parameter | substitute null | assign word || ${parameter:?word}| substitute parameter | error, exit | error, exit || ${parameter?word}| substitute parameter | substitute null | error, exit || ${parameter:+word}| substitute word | substitute null | substitute null || ${parameter+word}| substitute word | substitute word | substitute null |+--------------------+----------------------+-----------------+-----------------+
Em todos os casos mostrados com "substituto", a expressão é substituída pelo valor mostrado. Em todos os casos mostrados com "assign", o parâmetro recebe esse valor, o que também substitui a expressão.
Para mostrar isso em ação:
+--------------------+----------------------+-----------------+-----------------+|Expression| FOO="world"| FOO=""| unset FOO ||in script:|(Set and NotNull)|(SetButNull)|(Unset)|+--------------------+----------------------+-----------------+-----------------+| ${FOO:-hello}| world | hello | hello || ${FOO-hello}| world |""| hello || ${FOO:=hello}| world | FOO=hello | FOO=hello || ${FOO=hello}| world |""| FOO=hello || ${FOO:?hello}| world | error, exit | error, exit || ${FOO?hello}| world |""| error, exit || ${FOO:+hello}| hello |""|""|| ${FOO+hello}| hello | hello |""|+--------------------+----------------------+-----------------+-----------------+
@ HelloGoodbye Sim, funciona: set foo; echo ${1:-set but null or unset}ecos "foo"; set --; echo ${1:-set but null or unset}ecos set, mas nulo ...
Jens
4
@HelloGoodbye Os parâmetros de posição pode ser definida com, uh, set:-)
Jens
95
Esta resposta é muito confusa. Algum exemplo prático de como usar esta tabela?
Ben Davis
12
@BenDavis Os detalhes são explicados no link ao padrão POSIX, que faz referência ao capítulo em que a tabela é retirada. Uma construção que eu uso em quase todos os scripts que escrevo é : ${FOOBAR:=/etc/foobar.conf}definir um valor padrão para uma variável se ela estiver desmarcada ou nula.
Jens
1
parameteré qualquer nome de variável. wordé uma cadeia de caracteres a ser substituída, dependendo da sintaxe da tabela que você está usando e se a variável $parameterestá definida, definida, mas nula ou não definida. Não para tornar as coisas mais complicadas, mas wordtambém pode incluir variáveis! Isso pode ser muito útil para passar argumentos opcionais separados por um caractere. Por exemplo: ${parameter:+,${parameter}}gera uma vírgula separada ,$parameterse estiver definida, mas não nula. Neste caso, wordé,${parameter}
TrinitronX 19/01
260
Embora a maioria das técnicas descritas aqui esteja correta, o bash 4.2 suporta um teste real para a presença de uma variável ( man bash ), em vez de testar o valor da variável.
Notavelmente, essa abordagem não causará um erro quando usada para verificar uma variável não definida no modo set -u/ set -o nounset, diferente de muitas outras abordagens, como o uso [ -z.
No bash 4.1.2, independentemente de a variável estar definida, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected-bash: syntax error near 'aaa'
Dan
32
O argumento '-v' para o 'teste' interno foi adicionado no bash 4.2.
Ti Strga
19
o argumento -v foi adicionado como um complemento à opção -u shell (nounset). Com o 'nounset' ativado (set -u), o shell retornará um erro e será encerrado, se não for interativo. $ # foi bom para verificar os parâmetros posicionais. No entanto, as variáveis nomeadas precisavam de outra maneira, além de atrapalhar, para identificá-las como não definidas. É lamentável que esse recurso tenha chegado tão tarde, porque muitos tendem a ser compatíveis com a versão anterior; nesse caso, eles não podem usá-lo. A única outra opção é usar truques ou 'hacks' para contorná-lo, como mostrado acima, mas é mais deselegante.
Osirisgothra
2
Observe que isso não funciona para variáveis declaradas, mas não definidas. por exemplo,declare -a foo
miken32
17
É por isso que continuo lendo depois da resposta aceita / com a melhor votação.
24418 Joe
176
Existem várias maneiras de fazer isso, sendo uma delas a seguinte:
if[-z "$1"]
Isso será bem-sucedido se $ 1 for nulo ou não definido
Há uma diferença entre um parâmetro não definido e um parâmetro com um valor nulo.
chepner
21
Eu só quero ser pedante e ressaltar que esta é a resposta oposta ao que a pergunta coloca. As perguntas perguntam se a variável está definida, não se a variável não está definida.
Philluminati 3/13
47
[[ ]]nada mais é que uma armadilha da portabilidade. if [ -n "$1" ]deve ser usado aqui.
Jens
73
Esta resposta está incorreta. A pergunta pede uma maneira de saber se uma variável está definida, não se está definida para um valor não vazio. Dado foo="", $footem um valor, mas -zinforma apenas que está vazio. E -z $foovai explodir se você tiver set -o nounset.
Keith Thompson
4
Depende da definição de "variável está configurada". Se você deseja verificar se a variável está definida como uma sequência diferente de zero , a resposta mbranning está correta. Mas se você quiser verificar se a variável é declarada, mas não inicializada (ie foo=), a resposta de Russel está correta.
Fluxo
77
Eu sempre acho a tabela POSIX na outra resposta lenta para grok, então aqui está a minha opinião:
Observe que cada grupo (com e sem dois pontos anteriores) tem os mesmos casos definidos e não definidos ; portanto, a única coisa que difere é como os casos vazios são tratados.
Com os dois pontos anteriores, os casos vazios e não configurados são idênticos, então eu usaria aqueles sempre que possível (ou seja :=, use , não apenas =, porque o caso vazio é inconsistente).
Cabeçalhos:
definir meios VARIABLEnão está vazio ( VARIABLE="something")
significa vazioVARIABLE é vazio / nulo ( VARIABLE="")
meios VARIABLEnão definidos não existem ( unset VARIABLE)
Valores:
$VARIABLE significa que o resultado é o valor original da variável.
"default" significa que o resultado foi a sequência de substituição fornecida.
"" significa que o resultado é nulo (uma sequência vazia).
exit 127 significa que o script para de executar com o código de saída 127.
$(VARIABLE="default")significa que o resultado é o valor original da variável e a sequência de substituição fornecida é atribuída à variável para uso futuro.
Você corrigiu apenas aqueles que são erros de codificação reais (instâncias de indireção indesejada ao trabalhar com variáveis). Fiz uma edição para corrigir mais alguns casos em que o dólar faz diferença na interpretação da descrição. BTW, todas as variáveis de shell (com exceção de matrizes) são variáveis de string; pode acontecer que eles contenham uma sequência que possa ser interpretada como um número. Falar sobre cordas apenas obscurece a mensagem. Citações não têm nada a ver com seqüências de caracteres, são apenas uma alternativa para escapar. VARIABLE=""poderia ser escrito como VARIABLE=. Ainda assim, o primeiro é mais legível.
Palec
Obrigado pela tabela, é muito útil, no entanto, estou tentando fazer com que o script saia se não estiver definido ou vazio. Mas o código de saída que recebo é 1 e não 127.
Astronauta
64
Para ver se uma variável não é vazia, eu uso
if[[ $var ]];then...# `$var' expands to a nonempty string
O oposto testa se uma variável está desmarcada ou vazia:
if[[! $var ]];then...# `$var' expands to the empty string (set or not)
Para ver se uma variável está definida (vazia ou não vazia), eu uso
if[[ ${var+x}]];then...# `var' exists (empty or nonempty)if[[ ${1+x}]];then...# Parameter 1 exists (empty or nonempty)
O oposto testa se uma variável está desabilitada:
if[[! ${var+x}]];then...# `var' is not set at allif[[! ${1+x}]];then...# We were called with no arguments
Eu também tenho usado isso por um tempo; apenas de uma maneira reduzida:[ $isMac ] && param="--enable-shared"
@ Bhaskar Acho que é porque essa resposta já forneceu a mesma resposta (use ${variable+x}para obter o xiff $variabledefinido) quase meio ano antes. Também tem muito mais detalhes explicando por que está certo.
Mark Haferkamp
mas ${variable+x}é menos legível (e óbvia)
knocte
35
Em uma versão moderna do Bash (4.2 ou posterior, acho; não tenho certeza), tentaria o seguinte:
if[!-v SOMEVARIABLE ]#note the lack of a $ sigilthen
echo "Variable is unset"elif[-z "$SOMEVARIABLE"]then
echo "Variable is set to an empty string"else
echo "Variable is set to some string"fi
Observe também que [ -v "$VARNAME" ]não está incorreto, mas simplesmente executa um teste diferente. Suponha VARNAME=foo; então ele verifica se existe uma variável nomeada fooque está definida.
chepner
5
Nota para aqueles portabilidade querendo, -vnão é compatível com POSIX
kzh
Se alguém recebe [: -v: unexpected operator, é preciso garantir o uso em bashvez de sh.
koppor
25
if["$1"!=""];then
echo \$1 is setelse
echo \$1 is not setfi
Embora para argumentos seja normalmente melhor testar $ #, que é o número de argumentos, na minha opinião.
if[ $# -gt 0 ]; then
echo \$1 is setelse
echo \$1 is not setfi
O primeiro teste é para trás; Eu acho que você quer [ "$1" != "" ](ou [ -n "$1" ]) ...
Gordon Davisson
10
Isso falhará se $1estiver definido como a sequência vazia.
hellogoodbye
2
A segunda parte da resposta (contando parâmetros) é uma solução útil para a primeira parte da resposta que não está funcionando quando $1está definida como uma sequência vazia.
Mark Berry
Isso falhará se set -o nounsetestiver ativado.
Flimm
21
Nota
Estou dando uma resposta fortemente focada no Bash por causa da bashtag.
Resposta curta
Desde que você lide apenas com variáveis nomeadas no Bash, essa função sempre deve informar se a variável foi definida, mesmo que seja uma matriz vazia.
variable-is-set(){
declare -p "$1"&>/dev/null
}
Por que isso funciona
No Bash (pelo menos em 3.0), se varfor uma variável declarada / definida, declare -p varemite um declarecomando que definiria vara variável para qualquer que seja seu tipo e valor atuais e retorna o código de status 0(êxito). Se varnão for declarado, declare -p varemite uma mensagem de erro stderre retorna o código de status 1. Usando &>/dev/null, redireciona a saída normal stdoute a stderrsaída para /dev/null, para nunca mais ser vista, e sem alterar o código de status. Portanto, a função retorna apenas o código de status.
Por que outros métodos (às vezes) falham no Bash
[ -n "$var" ]: Isso verifica apenas se ${var[0]}não está vazio. (No Bash, $varé o mesmo que ${var[0]}.)
[ -n "${var+x}" ]: Apenas verifica se ${var[0]}está definido.
[ "${#var[@]}" != 0 ]: Isso verifica apenas se pelo menos um índice de $varestá definido.
Quando este método falha no Bash
Isso só funciona para variáveis nomeadas (incluindo $_), e não determinadas variáveis especiais ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ..., e qualquer outro que eu possa ter esquecido). Como nenhuma dessas são matrizes, o estilo POSIX [ -n "${var+x}" ]funciona para todas essas variáveis especiais. Mas tome cuidado para envolvê-lo em uma função, pois muitas variáveis especiais alteram valores / existência quando funções são chamadas.
Nota de compatibilidade do shell
Se o seu script tiver matrizes e você estiver tentando torná-lo compatível com o maior número possível de shells, considere usar em typeset -pvez de declare -p. Eu li que o ksh suporta apenas o primeiro, mas não pude testar isso. Eu sei que o Bash 3.0+ e o Zsh 5.5.1 suportam ambos typeset -pe declare -p, diferindo apenas em qual é uma alternativa para o outro. Mas não testei diferenças além dessas duas palavras-chave e não testei outras conchas.
Se você precisa que seu script seja compatível com POSIX sh, não poderá usar matrizes. Sem matrizes, [ -n "{$var+x}" ]funciona.
Código de comparação para diferentes métodos no Bash
Essa função desativa a variável var, evalé o código passado, executa testes para determinar se varé definido pelo evalcódigo d e, finalmente, mostra os códigos de status resultantes para os diferentes testes.
Estou pulando test -v var, [ -v var ]e [[ -v var ]]porque eles produzem resultados idênticos ao padrão POSIX [ -n "${var+x}" ], exigindo o Bash 4.2+. Também estou pulando typeset -pporque é o mesmo que declare -pnas conchas que testei (Bash 3.0 a 5.0 e Zsh 5.5.1).
is-var-set-after(){# Set var by passed expression.
unset var
eval"$1"# Run the tests, in increasing order of accuracy.[-n "$var"]# (index 0 of) var is nonempty
nonempty=$?[-n "${var+x}"]# (index 0 of) var is set, maybe empty
plus=$?["${#var[@]}"!=0]# var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?# Show test results.
printf '%30s: %2s %2s %2s %2s\n'"$1" $nonempty $plus $count $declared
}
Código do caso de teste
Observe que os resultados do teste podem ser inesperados devido ao Bash tratar os índices não numéricos da matriz como "0" se a variável não tiver sido declarada como uma matriz associativa. Além disso, matrizes associativas são válidas apenas no Bash 4.0+.
# Header.
printf '%30s: %2s %2s %2s %2s\n'"test"'-n''+x''#@''-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.
is-var-set-after "var=foo"# 0 0 0 0
is-var-set-after "var=(foo)"# 0 0 0 0
is-var-set-after "var=([0]=foo)"# 0 0 0 0
is-var-set-after "var=([x]=foo)"# 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)"# 0 0 0 0# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"# 1 0 0 0
is-var-set-after "var=([0]='')"# 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"# 1 1 0 0
is-var-set-after "var=([1]=foo)"# 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)"# 1 1 0 0# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"# 1 1 1 0
is-var-set-after "declare -a var"# 1 1 1 0
is-var-set-after "declare -A var"# 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"# 1 1 1 1
Saída de teste
As mnemónicas teste na linha de cabeçalho correspondem a [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], e declare -p var, respectivamente.
declare -p var &>/dev/null é (100%?) confiável para testar variáveis nomeadas no Bash desde pelo menos 3,0.
[ -n "${var+x}" ] é confiável em situações compatíveis com POSIX, mas não pode manipular matrizes.
Existem outros testes para verificar se uma variável não é vazia e para verificar variáveis declaradas em outros shells. Mas esses testes não são adequados para scripts Bash nem POSIX.
Das respostas que tentei, essa ( declare -p var &>/dev/null) é a ÚNICA que funciona. OBRIGADO!
user1387866
2
@ mark-haferkamp Tentei editar sua resposta para adicionar o "/" crítico anterior ao seu código de função para que ele lesse, ... &> /dev/nullmas o SO não me permitiria editar um único caractere 🙄 (deve ter> 6 caracteres - até tentei adicionar espaço em branco mas não funcionou). Além disso, pode valer a pena alterar a função para alternar $1para uma amostra denominada variável (por exemplo OUTPUT_DIR), pois, como você apontou, variáveis especiais como $1não funcionam aqui. Enfim, é uma edição crítica, caso contrário, o código está procurando criar um arquivo chamado nullem um diretório relativo chamado dev. Entre - ótima resposta!
Joehanna 23/11/19
Além disso, usando o nome da variável sem o prefixo $ também funciona: declare -p PATH &> /dev/nullretorna 0 onde, como declare -p ASDFASDGFASKDF &> /dev/nullretorna 1. (sobre o bash 5.0.11 (1) -release)
joehanna
1
Ótimo trabalho! 1 palavra de cautela: declare vardeclara var uma variável, mas não a define em termos de set -o nounset: Teste comdeclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche 25/11/19
@joehanna Obrigado por capturar essa falta /! Corrigi isso, mas acho que a lógica é confusa o suficiente para justificar uma função, especialmente à luz do comentário de @ xebeche. @xebeche Isso é inconveniente para a minha resposta ... Parece que vou ter que tentar algo como declare -p "$1" | grep =ou test -v "$1".
Mark Haferkamp 02/12/19
19
Para aqueles que procuram verificar se não estão definidos ou vazios quando em um script com set -u:
if[-z "${var-}"];then
echo "Must provide var environment variable. Exiting...."
exit 1fi
A [ -z "$var" ]verificação regular falhará com var; unbound variableif, set -umas se [ -z "${var-}" ]expandirá para a string vazia, se varestiver desativada sem falha.
Está faltando dois pontos. Deveria ser ${var:-}, não ${var-}. Mas no Bash, posso confirmar que funciona mesmo sem os dois pontos.
Palec
3
${var:-}e ${var-}significa coisas diferentes. ${var:-}expandirá para a string vazia se varnão estiver definido ou nulo e ${var-}expandirá para a string vazia apenas se não estiver definido.
RubenLaguna
Acabei de aprender algo novo, obrigado! A omissão dos dois pontos resulta em um teste apenas para um parâmetro não definido. Em outras palavras, se os dois pontos estiverem incluídos, o operador testa a existência dos dois parâmetros e se seu valor não é nulo; se os dois pontos forem omitidos, o operador testa apenas a existência. Não faz diferença aqui, mas é bom saber.
Palec
17
Você quer sair se não estiver definido
Isso funcionou para mim. Eu queria que meu script saísse com uma mensagem de erro se um parâmetro não estivesse definido.
#!/usr/bin/env bashset-o errexit
# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
Isso retorna com um erro quando é executado
peek@peek:~$ ./setver.sh
./setver.sh: line 13:1:You must pass a version of the format 0.0.0 as the only argument
Marque apenas, sem saída - Vazio e Desativado são INVÁLIDOS
Tente esta opção se você quiser apenas verificar se o valor configurado = VALID ou não configurado / vazio = INVALID.
Para verificar se uma variável está configurada com um valor não vazio, use [ -n "$x" ], como outros já indicaram.
Na maioria das vezes, é uma boa idéia tratar uma variável que tenha um valor vazio da mesma maneira que uma variável que não esteja definida. Mas você pode distinguir os dois se precisar: [ -n "${x+set}" ]( "${x+set}"expande para setse xestiver definido e para a sequência vazia, se xnão estiver definido ).
Para verificar se um parâmetro foi aprovado, teste $#, que é o número de parâmetros passados para a função (ou para o script, quando não estiver em uma função) (consulte a resposta de Paulo ).
Leia a seção "Expansão de parâmetros" da bashpágina de manual. A expansão de parâmetro não fornece um teste geral para uma variável que está sendo definida, mas há várias coisas que você pode fazer em um parâmetro, se não estiver definido.
Por exemplo:
function a {
first_arg=${1-foo}# rest of the function}
será first_argigual a $1se for atribuído, caso contrário, ele usará o valor "foo". Se aabsolutamente for necessário usar um único parâmetro e não existir um bom padrão, você poderá sair com uma mensagem de erro quando nenhum parâmetro for fornecido:
function a {: ${1?a must take a single argument}# rest of the function}
(Observe o uso de :como um comando nulo, que apenas expande os valores de seus argumentos. Não queremos fazer nada $1neste exemplo, basta sair se não estiver definido)
Usar [[ -z "$var" ]]é a maneira mais fácil de saber se uma variável foi configurada ou não, mas essa opção -znão faz distinção entre uma variável não configurada e uma variável definida como uma sequência vazia:
As respostas acima não funcionam quando a opção Bash set -uestá ativada. Além disso, eles não são dinâmicos, por exemplo, como testar a variável com o nome "dummy" definido? Tente o seguinte:
is_var_defined(){if[ $# -ne 1 ]then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1fi# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.# Example: $1="var"# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"# Code execute: [ ! -z ${var:-} ]eval"[ ! -z \${$1:-} ]"return $?# Pedantic.}
você precisa de aspas $1, ie [ ! -z "$1" ]. Ou você pode escrever [[ ! -z $1 ]]em bash / ksh / zsh.
Gilles 'SO- stop be evil' em
5
Isso falhará se $1estiver definido como a sequência vazia.
hellogoodbye
4
Minha maneira preferida é esta:
$ var=10
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
Então, basicamente, se uma variável é definida, ela se torna "uma negação do resultado false" (o que será true= "está definido").
E, se não estiver definido, ele se tornará "uma negação do resultado true" (conforme o resultado vazio for avaliado true) (assim terminará como sendo false= "NÃO definido").
if[[ ${1:+isset}]]then echo "It was set and not null.">&2else echo "It was not set or it was null.">&2fiif[[ ${1+isset}]]then echo "It was set but might be null.">&2else echo "It was was not set.">&2fi
Bem-vindo ao StackOverflow. Embora sua resposta seja apreciada, é melhor fornecer mais do que apenas código. Você poderia adicionar raciocínio à sua resposta ou uma pequena explicação? Consulte esta página para outras idéias sobre como expandir sua resposta.
Celeo
0
É isso que eu uso todos os dias:
## Check if a variable is set# param1 name of the variable#function is_set(){[[-n "${1}"]]&& test -n "$(eval "echo "\${${1}+x}"")"}
Isso funciona bem no Linux e Solaris até o bash 3.0.
Desde Bash 2.0+ expansão indireta está disponível. Você poderia substituir a longa e complexa (com um eval também incluído) test -n "$(eval "echo "\${${1}+x}"")"para o equivalente:[[ ${!1+x} ]]
0
Eu gosto de funções auxiliares para esconder os detalhes brutos do bash. Nesse caso, fazer isso adiciona ainda mais grossura (oculta):
# The first ! negates the result (can't use -n to achieve this)# the second ! expands the content of varname (can't do ${$varname})functionIsDeclared_Tricky{local varname="$1"![-z ${!varname+x}]}
Como tive bugs pela primeira vez nesta implementação (inspirada nas respostas de Jens e Lionel), criei uma solução diferente:
# Ask for the properties of the variable - fails if not declaredfunctionIsDeclared(){
declare -p $1 &>/dev/null
}
Acho que é mais direto, mais bash e mais fácil de entender / lembrar. O caso de teste mostra que é equivalente:
function main(){
declare -i xyz
local foo
local bar=local baz=''IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"IsDeclared xyz; echo "IsDeclared xyz: $?"IsDeclared foo; echo "IsDeclared foo: $?"IsDeclared bar; echo "IsDeclared bar: $?"IsDeclared baz; echo "IsDeclared baz: $?"}
main
O caso de teste, também mostra que local varnão NÃO declaram var (a não ser seguido por '='). Por algum tempo, pensei em declarar variáveis dessa maneira, apenas para descobrir agora que apenas expressei minha intenção ... Acho que não é uma operação.
Eu principalmente uso esse teste para fornecer (e retornar) parâmetros para funções de uma maneira um pouco "elegante" e segura (quase semelhante a uma interface ...):
#auxiliary functionsfunction die(){
echo "Error: $1"; exit 1}function assertVariableDeclared(){IsDeclared"$1"|| die "variable not declared: $1"}function expectVariables(){while(( $# > 0 )); do
assertVariableDeclared $1; shift
done}# actual examplefunction exampleFunction(){
expectVariables inputStr outputStr
outputStr="$inputStr world!"}function bonus(){local inputStr='Hello'local outputStr=# remove this to trigger error
exampleFunction
echo $outputStr
}
bonus
não vai funcionar quando você tem set -u, com efeito, que irá imprimir o unboud variableerro
Michael Heuberger
0
Sumário
Use test -n "${var-}"para verificar se a variável não está vazia (e, portanto, também deve ser definida / definida)
Use test ! -z "${var+}"para verificar se a variável está definida / definida (mesmo que esteja vazia)
Observe que o primeiro caso de uso é muito mais comum em scripts de shell e é isso que você geralmente desejará usar.
Notas
Esta solução deve funcionar em todos os shells POSIX (sh, bash, zsh, ksh, dash)
Algumas das outras respostas para esta pergunta estão corretas, mas podem ser confusas para pessoas inexperientes em scripts de shell, então eu queria fornecer uma resposta TLDR que seja menos confusa para essas pessoas.
Explicação
Para entender como essa solução funciona, você precisa entender o comando POSIXtest e a expansão dos parâmetros do shell POSIX ( spec ), portanto, vamos cobrir o básico absoluto necessário para entender a resposta.
O comando test avalia uma expressão e retorna verdadeiro ou falso (por meio do status de saída). O operador -nretornará true se o operando for uma sequência não vazia. Por exemplo, test -n "a"retorna true, enquanto test -n ""retorna false. Agora, para verificar se uma variável não está vazia (o que significa que deve ser definida), você pode usar test -n "$var". No entanto, alguns scripts de shell têm uma opção set ( set -u) que faz com que qualquer referência a variáveis indefinidas emita um erro; portanto, se a variável varnão estiver definida, a expressão $acausará um erro. Para lidar com esse caso corretamente, você deve usar a expansão de variável, que informará o shell para substituir a variável por uma sequência alternativa, se não estiver definida, evitando o erro mencionado acima.
A expansão da variável ${var-}significa: se a variável não varestiver definida (também chamada de "não definida"), substitua-a por uma sequência vazia. Portanto test -n "${var-}", retornará true se $varnão estiver vazio, o que quase sempre é o que você deseja verificar nos scripts de shell. A verificação inversa, se $varfor indefinida ou vazia, seria test -z "${var-}".
Agora, para o segundo caso de uso: verificando se a variável varestá definida, vazia ou não. Este é um caso de uso menos comum e um pouco mais complexo, e eu aconselho você a ler a ótima resposta de Lionels para entendê-la melhor.
Eu acho que você quer dizer set -o nounset, não set -o noun set. Isso funciona apenas para variáveis que foram exporteditadas. Ele também altera suas configurações de uma maneira difícil de desfazer.
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
.-v
testes, embora isso pareça estar disponível apenas em novas versõesbash
e não portável em conchas.Respostas:
(Normalmente) O caminho certo
onde
${var+x}
é uma expansão de parâmetro que avalia como nada se nãovar
estiver definida e substitui a string dex
outra forma.Cotação Digressão
As aspas podem ser omitidas (é o que podemos dizer em
${var+x}
vez de"${var+x}"
), porque essa sintaxe e uso garantem que isso só será expandido para algo que não requer aspas (uma vez que se expande parax
(que não contém quebras de palavras e não precisa de aspas) ou para nada (que resulta em[ -z ]
, que avalia convenientemente o mesmo valor (verdadeiro) que[ -z "" ]
também)).No entanto, embora as aspas possam ser omitidas com segurança, e isso não foi imediatamente óbvio para todos (nem sequer ficou claro para o primeiro autor desta explicação de citações que também é um dos principais codificadores do Bash), às vezes seria melhor escrever a solução entre aspas
[ -z "${var+x}" ]
, pelo menor custo possível de uma penalidade de velocidade O (1). O primeiro autor também adicionou isso como um comentário ao lado do código usando esta solução, fornecendo o URL para esta resposta, que agora também inclui a explicação de por que as aspas podem ser omitidas com segurança.(Muitas vezes) O caminho errado
Isso geralmente está errado porque não faz distinção entre uma variável que está desconfigurada e uma variável que está configurada para a cadeia vazia. Ou seja, se
var=''
, então, a solução acima produzirá "var is blank".A distinção entre não definido e "definido para a cadeia vazia" é essencial em situações em que o usuário precisa especificar uma extensão ou lista adicional de propriedades, e que não a especificação dos padrões é um valor não vazio, enquanto a cadeia vazia deve ser especificada. faça com que o script use uma extensão vazia ou uma lista de propriedades adicionais.
A distinção pode não ser essencial em todos os cenários. Nesses casos
[ -z "$var" ]
, tudo ficará bem.fonte
${var+x}
é a substituição correta a ser usada. Usar[ -z ${var:+x} ]
não produz resultados diferentes de[ -z "$var" ]
.[ -z "" -a -z ${var+x} ]
entrabash: [: argument expected
no bash 4.3-ubuntu (mas não, por exemplo, zsh). Eu realmente não gosto da resposta usando uma sintaxe que funciona em alguns casos.[ -z $var ]
não é mais "errado" do que omitir aspas. De qualquer forma, você está fazendo suposições sobre sua entrada. Se você está bem tratando uma string vazia como não definida,[ -z $var ]
é tudo o que precisa.Para verificar a variável de sequência não nula / diferente de zero, ou seja, se configurada, use
É o oposto de
-z
. Eu me pego usando-n
mais de-z
.Você usaria como:
fonte
[[ ]]
excesso[ ]
, pois[[ ]]
é mais poderoso e causa menos problemas em determinadas situações (veja esta pergunta para obter uma explicação da diferença entre os dois). A pergunta pede especificamente uma solução bash e não menciona nenhum requisito de portabilidade.[]
funciona melhor especialmente para scripts shell (não bash).set -u
.-n
é o teste padrão, de forma mais simples[ "$1" ]
ou também[[ $1 ]]
funciona. Observe também que a[[ ]]
citação é desnecessária .Veja como testar se um parâmetro está desmarcado ou vazio ("Nulo") ou definido com um valor :
Fonte: POSIX: Expansão do parâmetro :
Para mostrar isso em ação:
fonte
set foo; echo ${1:-set but null or unset}
ecos "foo";set --; echo ${1:-set but null or unset}
ecos set, mas nulo ...set
:-): ${FOOBAR:=/etc/foobar.conf}
definir um valor padrão para uma variável se ela estiver desmarcada ou nula.parameter
é qualquer nome de variável.word
é uma cadeia de caracteres a ser substituída, dependendo da sintaxe da tabela que você está usando e se a variável$parameter
está definida, definida, mas nula ou não definida. Não para tornar as coisas mais complicadas, masword
também pode incluir variáveis! Isso pode ser muito útil para passar argumentos opcionais separados por um caractere. Por exemplo:${parameter:+,${parameter}}
gera uma vírgula separada,$parameter
se estiver definida, mas não nula. Neste caso,word
é,${parameter}
Embora a maioria das técnicas descritas aqui esteja correta, o bash 4.2 suporta um teste real para a presença de uma variável ( man bash ), em vez de testar o valor da variável.
Notavelmente, essa abordagem não causará um erro quando usada para verificar uma variável não definida no modo
set -u
/set -o nounset
, diferente de muitas outras abordagens, como o uso[ -z
.fonte
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
Existem várias maneiras de fazer isso, sendo uma delas a seguinte:
Isso será bem-sucedido se $ 1 for nulo ou não definido
fonte
[[ ]]
nada mais é que uma armadilha da portabilidade.if [ -n "$1" ]
deve ser usado aqui.foo=""
,$foo
tem um valor, mas-z
informa apenas que está vazio. E-z $foo
vai explodir se você tiverset -o nounset
.foo=
), a resposta de Russel está correta.Eu sempre acho a tabela POSIX na outra resposta lenta para grok, então aqui está a minha opinião:
Observe que cada grupo (com e sem dois pontos anteriores) tem os mesmos casos definidos e não definidos ; portanto, a única coisa que difere é como os casos vazios são tratados.
Com os dois pontos anteriores, os casos vazios e não configurados são idênticos, então eu usaria aqueles sempre que possível (ou seja
:=
, use , não apenas=
, porque o caso vazio é inconsistente).Cabeçalhos:
VARIABLE
não está vazio (VARIABLE="something"
)VARIABLE
é vazio / nulo (VARIABLE=""
)VARIABLE
não definidos não existem (unset VARIABLE
)Valores:
$VARIABLE
significa que o resultado é o valor original da variável."default"
significa que o resultado foi a sequência de substituição fornecida.""
significa que o resultado é nulo (uma sequência vazia).exit 127
significa que o script para de executar com o código de saída 127.$(VARIABLE="default")
significa que o resultado é o valor original da variável e a sequência de substituição fornecida é atribuída à variável para uso futuro.fonte
VARIABLE=""
poderia ser escrito comoVARIABLE=
. Ainda assim, o primeiro é mais legível.Para ver se uma variável não é vazia, eu uso
O oposto testa se uma variável está desmarcada ou vazia:
Para ver se uma variável está definida (vazia ou não vazia), eu uso
O oposto testa se uma variável está desabilitada:
fonte
[ $isMac ] && param="--enable-shared"
${variable+x}
para obter ox
iff$variable
definido) quase meio ano antes. Também tem muito mais detalhes explicando por que está certo.${variable+x}
é menos legível (e óbvia)Em uma versão moderna do Bash (4.2 ou posterior, acho; não tenho certeza), tentaria o seguinte:
fonte
[ -v "$VARNAME" ]
não está incorreto, mas simplesmente executa um teste diferente. SuponhaVARNAME=foo
; então ele verifica se existe uma variável nomeadafoo
que está definida.-v
não é compatível com POSIX[: -v: unexpected operator
, é preciso garantir o uso embash
vez desh
.Embora para argumentos seja normalmente melhor testar $ #, que é o número de argumentos, na minha opinião.
fonte
[ "$1" != "" ]
(ou[ -n "$1" ]
) ...$1
estiver definido como a sequência vazia.$1
está definida como uma sequência vazia.set -o nounset
estiver ativado.Nota
Estou dando uma resposta fortemente focada no Bash por causa da
bash
tag.Resposta curta
Desde que você lide apenas com variáveis nomeadas no Bash, essa função sempre deve informar se a variável foi definida, mesmo que seja uma matriz vazia.
Por que isso funciona
No Bash (pelo menos em 3.0), se
var
for uma variável declarada / definida,declare -p var
emite umdeclare
comando que definiriavar
a variável para qualquer que seja seu tipo e valor atuais e retorna o código de status0
(êxito). Sevar
não for declarado,declare -p var
emite uma mensagem de errostderr
e retorna o código de status1
. Usando&>/dev/null
, redireciona a saída normalstdout
e astderr
saída para/dev/null
, para nunca mais ser vista, e sem alterar o código de status. Portanto, a função retorna apenas o código de status.Por que outros métodos (às vezes) falham no Bash
Quando este método falha no Bash
Isso só funciona para variáveis nomeadas (incluindo
$_
), e não determinadas variáveis especiais ($!
,$@
,$#
,$$
,$*
,$?
,$-
,$0
,$1
,$2
, ..., e qualquer outro que eu possa ter esquecido). Como nenhuma dessas são matrizes, o estilo POSIX[ -n "${var+x}" ]
funciona para todas essas variáveis especiais. Mas tome cuidado para envolvê-lo em uma função, pois muitas variáveis especiais alteram valores / existência quando funções são chamadas.Nota de compatibilidade do shell
Se o seu script tiver matrizes e você estiver tentando torná-lo compatível com o maior número possível de shells, considere usar em
typeset -p
vez dedeclare -p
. Eu li que o ksh suporta apenas o primeiro, mas não pude testar isso. Eu sei que o Bash 3.0+ e o Zsh 5.5.1 suportam ambostypeset -p
edeclare -p
, diferindo apenas em qual é uma alternativa para o outro. Mas não testei diferenças além dessas duas palavras-chave e não testei outras conchas.Se você precisa que seu script seja compatível com POSIX sh, não poderá usar matrizes. Sem matrizes,
[ -n "{$var+x}" ]
funciona.Código de comparação para diferentes métodos no Bash
Essa função desativa a variável
var
,eval
é o código passado, executa testes para determinar sevar
é definido peloeval
código d e, finalmente, mostra os códigos de status resultantes para os diferentes testes.Estou pulando
test -v var
,[ -v var ]
e[[ -v var ]]
porque eles produzem resultados idênticos ao padrão POSIX[ -n "${var+x}" ]
, exigindo o Bash 4.2+. Também estou pulandotypeset -p
porque é o mesmo quedeclare -p
nas conchas que testei (Bash 3.0 a 5.0 e Zsh 5.5.1).Código do caso de teste
Observe que os resultados do teste podem ser inesperados devido ao Bash tratar os índices não numéricos da matriz como "0" se a variável não tiver sido declarada como uma matriz associativa. Além disso, matrizes associativas são válidas apenas no Bash 4.0+.
Saída de teste
As mnemónicas teste na linha de cabeçalho correspondem a
[ -n "$var" ]
,[ -n "${var+x}" ]
,[ "${#var[@]}" != 0 ]
, edeclare -p var
, respectivamente.Sumário
fonte
declare -p var &>/dev/null
) é a ÚNICA que funciona. OBRIGADO!... &> /dev/null
mas o SO não me permitiria editar um único caractere 🙄 (deve ter> 6 caracteres - até tentei adicionar espaço em branco mas não funcionou). Além disso, pode valer a pena alterar a função para alternar$1
para uma amostra denominada variável (por exemploOUTPUT_DIR
), pois, como você apontou, variáveis especiais como$1
não funcionam aqui. Enfim, é uma edição crítica, caso contrário, o código está procurando criar um arquivo chamadonull
em um diretório relativo chamadodev
. Entre - ótima resposta!declare -p PATH &> /dev/null
retorna 0 onde, comodeclare -p ASDFASDGFASKDF &> /dev/null
retorna 1. (sobre o bash 5.0.11 (1) -release)declare var
declara var uma variável, mas não a define em termos deset -o nounset
: Teste comdeclare foo bar=; set -o nounset; echo $bar; echo $foo
/
! Corrigi isso, mas acho que a lógica é confusa o suficiente para justificar uma função, especialmente à luz do comentário de @ xebeche. @xebeche Isso é inconveniente para a minha resposta ... Parece que vou ter que tentar algo comodeclare -p "$1" | grep =
outest -v "$1"
.Para aqueles que procuram verificar se não estão definidos ou vazios quando em um script com
set -u
:A
[ -z "$var" ]
verificação regular falhará comvar; unbound variable
if,set -u
mas se[ -z "${var-}" ]
expandirá para a string vazia, sevar
estiver desativada sem falha.fonte
${var:-}
, não${var-}
. Mas no Bash, posso confirmar que funciona mesmo sem os dois pontos.${var:-}
e${var-}
significa coisas diferentes.${var:-}
expandirá para a string vazia sevar
não estiver definido ou nulo e${var-}
expandirá para a string vazia apenas se não estiver definido.Você quer sair se não estiver definido
Isso funcionou para mim. Eu queria que meu script saísse com uma mensagem de erro se um parâmetro não estivesse definido.
Isso retorna com um erro quando é executado
Marque apenas, sem saída - Vazio e Desativado são INVÁLIDOS
Tente esta opção se você quiser apenas verificar se o valor configurado = VALID ou não configurado / vazio = INVALID.
Ou, mesmo testes breves ;-)
Marque apenas, sem saída - Somente vazio é INVÁLIDO
E esta é a resposta para a pergunta. Use isso se você quiser apenas verificar se o valor definido / vazio = VÁLIDO ou não definido = INVÁLIDO.
OBSERVAÇÃO, o "1" em "..- 1}" é insignificante, pode ser qualquer coisa (como x)
Testes curtos
Dedico esta resposta a @ mklement0 (comentários) que me desafiou a responder à pergunta com precisão.
Referência http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
fonte
Para verificar se uma variável está configurada com um valor não vazio, use
[ -n "$x" ]
, como outros já indicaram.Na maioria das vezes, é uma boa idéia tratar uma variável que tenha um valor vazio da mesma maneira que uma variável que não esteja definida. Mas você pode distinguir os dois se precisar:
[ -n "${x+set}" ]
("${x+set}"
expande paraset
sex
estiver definido e para a sequência vazia, sex
não estiver definido ).Para verificar se um parâmetro foi aprovado, teste
$#
, que é o número de parâmetros passados para a função (ou para o script, quando não estiver em uma função) (consulte a resposta de Paulo ).fonte
Leia a seção "Expansão de parâmetros" da
bash
página de manual. A expansão de parâmetro não fornece um teste geral para uma variável que está sendo definida, mas há várias coisas que você pode fazer em um parâmetro, se não estiver definido.Por exemplo:
será
first_arg
igual a$1
se for atribuído, caso contrário, ele usará o valor "foo". Sea
absolutamente for necessário usar um único parâmetro e não existir um bom padrão, você poderá sair com uma mensagem de erro quando nenhum parâmetro for fornecido:(Observe o uso de
:
como um comando nulo, que apenas expande os valores de seus argumentos. Não queremos fazer nada$1
neste exemplo, basta sair se não estiver definido)fonte
: ${var?message}
.No bash, você pode usar
-v
dentro do[[ ]]
built-in:fonte
Usar
[[ -z "$var" ]]
é a maneira mais fácil de saber se uma variável foi configurada ou não, mas essa opção-z
não faz distinção entre uma variável não configurada e uma variável definida como uma sequência vazia:É melhor checá-lo de acordo com o tipo de variável: variável env, parâmetro ou variável regular.
Para uma variável env:
Para um parâmetro (por exemplo, para verificar a existência do parâmetro
$5
):Para uma variável regular (usando uma função auxiliar, para fazê-lo de maneira elegante):
Notas:
fonte
As respostas acima não funcionam quando a opção Bash
set -u
está ativada. Além disso, eles não são dinâmicos, por exemplo, como testar a variável com o nome "dummy" definido? Tente o seguinte:Relacionado: No Bash, como faço para testar se uma variável está definida no modo "-u"
fonte
eval "[ ! -z \${$1:-} ]"
para avaliação indireta:[ ! -z ${!1:-} ];
.Você pode fazer:
fonte
-n
e não negar o-z
.$1
, ie[ ! -z "$1" ]
. Ou você pode escrever[[ ! -z $1 ]]
em bash / ksh / zsh.$1
estiver definido como a sequência vazia.Minha maneira preferida é esta:
Então, basicamente, se uma variável é definida, ela se torna "uma negação do resultado
false
" (o que serátrue
= "está definido").E, se não estiver definido, ele se tornará "uma negação do resultado
true
" (conforme o resultado vazio for avaliadotrue
) (assim terminará como sendofalse
= "NÃO definido").fonte
Ou
Ou
Ou
fonte
Em um shell, você pode usar o
-z
operador True, se o comprimento da string for zero.Um one-liner simples para definir o padrão,
MY_VAR
se não estiver definido, caso contrário, opcionalmente, você pode exibir a mensagem:fonte
fonte
$1
,$2
e até$N
sempre está definido. Desculpe, isso é falha.Encontrei um código (muito) melhor para fazer isso, se você quiser verificar alguma coisa
$@
.Por que isso tudo? Tudo
$@
existe no Bash, mas, por padrão, está em branco,test -z
etest -n
não pode ajudá-lo.Atualização: Você também pode contar o número de caracteres em um parâmetro.
fonte
fonte
É isso que eu uso todos os dias:
Isso funciona bem no Linux e Solaris até o bash 3.0.
fonte
test -n "$(eval "echo "\${${1}+x}"")"
para o equivalente:[[ ${!1+x} ]]
Eu gosto de funções auxiliares para esconder os detalhes brutos do bash. Nesse caso, fazer isso adiciona ainda mais grossura (oculta):
Como tive bugs pela primeira vez nesta implementação (inspirada nas respostas de Jens e Lionel), criei uma solução diferente:
Acho que é mais direto, mais bash e mais fácil de entender / lembrar. O caso de teste mostra que é equivalente:
O caso de teste, também mostra que
local var
não NÃO declaram var (a não ser seguido por '='). Por algum tempo, pensei em declarar variáveis dessa maneira, apenas para descobrir agora que apenas expressei minha intenção ... Acho que não é uma operação.BÔNUS: caso de uso
Eu principalmente uso esse teste para fornecer (e retornar) parâmetros para funções de uma maneira um pouco "elegante" e segura (quase semelhante a uma interface ...):
Se chamado com all requer variáveis declaradas:
outro:
fonte
Depois de examinar todas as respostas, isso também funciona:
se você não colocar no
SOME_VAR
lugar do que eu tenho$SOME_VAR
, será definido como um valor vazio;$
é necessário para que isso funcione.fonte
set -u
, com efeito, que irá imprimir ounboud variable
erroSumário
test -n "${var-}"
para verificar se a variável não está vazia (e, portanto, também deve ser definida / definida)test ! -z "${var+}"
para verificar se a variável está definida / definida (mesmo que esteja vazia)Observe que o primeiro caso de uso é muito mais comum em scripts de shell e é isso que você geralmente desejará usar.
Notas
Explicação
Para entender como essa solução funciona, você precisa entender o comando POSIX
test
e a expansão dos parâmetros do shell POSIX ( spec ), portanto, vamos cobrir o básico absoluto necessário para entender a resposta.O comando test avalia uma expressão e retorna verdadeiro ou falso (por meio do status de saída). O operador
-n
retornará true se o operando for uma sequência não vazia. Por exemplo,test -n "a"
retorna true, enquantotest -n ""
retorna false. Agora, para verificar se uma variável não está vazia (o que significa que deve ser definida), você pode usartest -n "$var"
. No entanto, alguns scripts de shell têm uma opção set (set -u
) que faz com que qualquer referência a variáveis indefinidas emita um erro; portanto, se a variávelvar
não estiver definida, a expressão$a
causará um erro. Para lidar com esse caso corretamente, você deve usar a expansão de variável, que informará o shell para substituir a variável por uma sequência alternativa, se não estiver definida, evitando o erro mencionado acima.A expansão da variável
${var-}
significa: se a variável nãovar
estiver definida (também chamada de "não definida"), substitua-a por uma sequência vazia. Portantotest -n "${var-}"
, retornará true se$var
não estiver vazio, o que quase sempre é o que você deseja verificar nos scripts de shell. A verificação inversa, se$var
for indefinida ou vazia, seriatest -z "${var-}"
.Agora, para o segundo caso de uso: verificando se a variável
var
está definida, vazia ou não. Este é um caso de uso menos comum e um pouco mais complexo, e eu aconselho você a ler a ótima resposta de Lionels para entendê-la melhor.fonte
Para verificar se um var está definido ou não
fonte
$var
estiver definido como a sequência vazia.Se você deseja testar se uma variável está vinculada ou não, isso funciona bem, mesmo depois de ativar a opção de conjunto de substantivos:
fonte
set -o nounset
, nãoset -o noun set
. Isso funciona apenas para variáveis que foramexport
editadas. Ele também altera suas configurações de uma maneira difícil de desfazer.