Para a versão antiga da resposta, consulte a segunda parte desta resposta. Se você quiser saber detalhes, continue lendo
A causa do problema
Na própria pergunta, é relatado que o OP vê too many arguments error
, o que, quando testado bash
, não parece ser o caso:
$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected
Com o /bin/sh
qual está realmente vinculado ao /bin/dash
Ubuntu, o erro relatado da seguinte maneira:
$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator
E o autônomo /bin/test
também:
$ /usr/bin/test $1 != ''
/usr/bin/test: missing argument after ‘’
Sidenote: Se você está se perguntando o que é /usr/bin/test
e porque eu estou usando bash
e sh
, em seguida, você deve saber que [
é alias para test
o comando, que também existe como executável autônomo ou mais comumente - como shell built-in que é o que cada shell usará primeiro . Quanto às if
instruções, elas operam nas estátuas de saída dos comandos, daí o motivo [
e test
são comandos, com tudo o mais sendo argumentos para esses comandos - a ordem incorreta desses argumentos da linha de comando leva a erros.
Voltar ao tópico: não está claro como o OP recebeu o erro não relacionado. No entanto, nos três casos, o problema é o mesmo - a variável não definida será tratada como vazia, portanto, o que o shell vê com essas variáveis não citadas é
[ != '' ]
que quebra a sintaxe que test
entende. Lembra do que eu disse sobre a ordem imprópria dos argumentos da linha de comando? Por isso, é importante citar. Vamos ativar a saída de diagnóstico e ver o que o shell executa:
$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ]
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars
Melhor maneira de testar variáveis não definidas
Uma abordagem muito frequente que você vê ao redor é a seguinte:
if [ "x$var1" == "x" ] && [ "x$var2" == "x" ];
then
echo "both variables are null"
fi
Para citar Gilles :
Em ["x $ 1" = "x"], o prefixo x garante que x "$ 1" não possa se parecer com um operador e, portanto, a única maneira pela qual o shell pode analisar esse teste é tratando = como um operador binário.
Presumivelmente, isso deve ser bastante portátil, já que eu os vi em /bin/sh
scripts. Também pode ser combinado como em
if [ "x${var1}${var2}" == "x" ]; then
...
fi
É claro que poderíamos usar a -z
bandeira, no entanto, de acordo com pesquisas em algumas conchas, particularmente o ksh88 (de acordo com Stephane Chazelas ), essa bandeira está com defeito.
Veja também