“teste -n && echo not empty” imprime “não vazio”. Esse comportamento é esperado?

7

O título diz tudo: Quando eu executo a seguinte linha

test -n && echo not empty

imprime "não vazio". Isso ocorre quando você tem uma variável vazia e testa o não-esvaziamento, esquecendo-se de citar o valor:

VAR=
test -n  $VAR  && echo wrong 1
test -n "$VAR" && echo wrong 2

Esse comportamento é esperado?

    
por daniel kullmann 27.01.2012 / 13:59

5 respostas

9

Sim, isso é um comportamento esperado. Quando apenas um argumento é passado para test , uma verificação de comprimento é executada. De man bash :

test and [ evaluate conditional expressions using a set of rules based on the number of arguments.

0 arguments: The expression is false.

1 argument: The expression is true if and only if the argument is not null.

Ou seja, essencialmente, é o equivalente de test foo , mas usando -n como a string.

    
por 27.01.2012 / 14:14
3

test -n é prima facie malformado, pois -n requer um argumento. Acredito que algumas implementações históricas o trataram como um erro de sintaxe (e retornaram um status diferente de zero). No entanto, em todas as conchas que você provavelmente encontrará no século 21, o comportamento é bem definido (por POSIX , seguindo a prática existente): se test tem apenas um argumento, então é verdadeiro se e somente se esse argumento não for vazio.

Observe que, se você deixar de fora as aspas, o teste pode acabar sendo falso para alguns valores não vazios de $VAR . Pode até imprimir uma mensagem de erro se houver caracteres globbing em $VAR .

VAR='foo -a -z bar'; test -n $VAR || echo "true... and false is false"
VAR='= n-'; test -n $VAR || echo "this is an equality test"
VAR='*'; test -n $VAR || echo "you may or may not see this depending on what files are in the current directory"

test -z $VAR está similarmente quebrado.

Ksh, bash e zsh têm uma construção condicional [[ … ]] que imita os utilitários tradicionais test e [ . Ao contrário de [ , que é um utilitário externo ou é um built-in que é analisado como um, [[ … ]] faz parte da sintaxe do shell. Não há palavra dividindo ou globbing dentro de [[ … ]] . [[ -n $VAR ]] está bem (contanto que você não se importe que seus scripts não sejam executados em outras camadas, como cinza).

    
por 27.01.2012 / 19:34
1

Verifique também [[ ... ]] , que não sofre esse comportamento:

[[ -n $VAR ]] && echo wrong 3
[[ -n "$VAR" ]] && echo wrong 4
    
por 27.01.2012 / 14:44
0

Como o bash buildin test e /usr/bin/test leva ao mesmo resultado, digo sim, é o comportamento esperado.

    
por 27.01.2012 / 14:09
0

Parece que você faz o seguinte:

VAR=
test -n $VAR && echo helloworld

É como se o argumento não estivesse lá:

test -n && echo helloworld

E, por algum motivo, quando o argumento não é fornecido, ele sempre executa o comando depois (ou seja, exibe o helloworld). Eu tentei isso em outro operador de uneiro e fez a mesma coisa:

FILENAME=
test -f $FILENAME && echo helloworld

Acho que se você quiser ter um comportamento esperado, é necessário citar o argumento:

VAR=
test -n "$VAR" && echo helloworld
FILE=
test -f "$FILE" && echo helloworld

O texto acima não gera nenhuma mensagem ecoando na tela.

Quanto a esse comportamento esperado? Não consigo encontrá-lo na documentação em qualquer lugar, mas parece bastante reproduzível e consistente.

    
por 28.01.2012 / 01:53

Tags