como verificar se $ 1 e $ 2 são nulos?

40

Estou executando algum script que passa o argumento string e quero fazer a declaração if else mostrada abaixo:

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

mas mostrou Error too many argument. Por quê?

taymindis Woon
fonte
Você deve fornecer 1. o comando que você chama de script e 2. a saída completa.
Lucio
2
Você deveria usar [[ ]]. Caso contrário, você deve citar suas variáveis.
Christophe De Troyer
Se $ 1 não existisse, então $ 2 se tornaria $ 1, o que faz com que o teste de $ 1 e $ 2 sendo nulo pareça irrelevante.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Não necessariamente irrelevante - em alguns casos, você deseja garantir que haja realmente algo em vez de cadeia em branco ou nula nos argumentos. $1pode estar desconfigurado ou configurado como string nula pelo usuário do script. Considere esta seqüência de comandos: $ set '' bardepois echo "x${1}x";Ambas as variáveis são definidas, mas um deles é nulo.
Sergiy Kolodyazhnyy

Respostas:

55

Tente usar o teste -z:

if [ -z "$1" ] && [ -z "$2" ]

Do homem bash:

-z string
   True if the length of string is zero.
Sylvain Pineau
fonte
Funciona para mim!
pengisgood
é interessante que a resposta mais votada e aceita realmente não responda à pergunta.
mehmet
Ao escrever scripts de shell portáteis, esse sinalizador deve ser usado com cuidado, pois em certos Unixes comerciais, esse sinalizador está com defeito. Veja minha resposta para fontes vinculadas.
Sergiy Kolodyazhnyy
14

Como isso está marcado bash, eu recomendo que você use a construção de teste estendida ( [[...]]) e esqueça as aspas:

if [[ -z $1 && -z $2 ]]; then
...

A menos que você esteja shbuscando compatibilidade com / POSIX, não há motivo para não usá-lo [[ ]].

muru
fonte
3

O seguinte também funciona,

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi
Avinash Raj
fonte
O &&e outros separadores de comandos lógicos não são permitidos no clássico test. Você tem que usar outras construções de teste em vez (como -a, eu acho)
Muru
3

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/shqual está realmente vinculado ao /bin/dashUbuntu, o erro relatado da seguinte maneira:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

E o autônomo /bin/testtambém:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Sidenote: Se você está se perguntando o que é /usr/bin/teste porque eu estou usando bashe sh, em seguida, você deve saber que [é alias para testo 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 ifinstruções, elas operam nas estátuas de saída dos comandos, daí o motivo [e testsã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 testentende. 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/shscripts. Também pode ser combinado como em

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

É claro que poderíamos usar a -zbandeira, 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

Sergiy Kolodyazhnyy
fonte
+1 para uma abordagem muito interessante.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Editado para torná-lo ainda mais interessante :) #
Sergiy Kolodyazhnyy
1

Acho que o título da postagem não é exato, pois a intenção da mensagem era verificar se $ 1 e $ 2 não são nulos. O exemplo dado estava faltando aspas duplas em $ 1 e $ 2 para funcionar. As variáveis ​​devem ser aspas duplas para serem expandidas ao comparar cadeias. Mas, verificar se $ 1 e $ 2 existem é o mesmo que verificar se $ 2 existem, pois não pode existir se $ 1 não existir. O comando 'if' também não é necessário neste caso, pois 'test' retorna true / false e usa '&&' como 'then' se return for 0 / true:

[ "$2" != '' ] && commands...

Mais simples, com -n (diferente de zero):

[ -n "$2" ] && commands...

Para "verificar se $ 1 e $ 2 são nulos" seria o mesmo que verificar se não há parâmetro:

[ $# -eq 0 ] && commands...
Guariba Som
fonte