Uso de -n e -z no teste integrado - Bash

0

Considere o seguinte no bash:

root@debian-lap:/tmp I=$(echo)
root@debian-lap:/tmp echo "$I"

root@debian-lap:/tmp [ -z "$I" ] && echo "TRUE" || echo "FALSE"
TRUE

Isso significa que a variável $ I é zero . O mesmo que consegui com o teste de negação para ver se a variável é diferente de zero, e ! torna o teste inverso, portanto, as verificações são variáveis zero

root@debian-lap:/tmp ! [ -n "$I" ] && echo "TRUE" || echo "FALSE"
TRUE
root@debian-lap:/tmp

Então, minha pergunta é: há casos especiais em que usar -z e ! -n , ou vice-versa ! -z e -n , já que eles estão basicamente fazendo o mesmo teste?

Obrigado

    
por fugitive 14.06.2017 / 17:05

2 respostas

2

Você recebe -n e -z pelo mesmo motivo que outros conjuntos de testes fornecem == e != , ou AND e NOT . Alguns casos de teste podem ser muito mais claros para os futuros mantenedores, evitando os negativos duplos. Além disso, como mencionado em um comentário acima, encarnações antigas de sh (ou seja, as conchas Bourne e Thompson), em oposição ao POSIX sh moderno não tinham uma palavra-chave ! para negar a veracidade das expressões test .

    
por 14.06.2017 / 17:38
6

1. [ -z "$var" ]
2. [ ! -n "$var" ]
3. ! [ -n "$var" ]
4. [ ! "$var" ]
5. [ "$var" = '' ]
6. [ ! "$var" != '' ]
7. [ '' = "$var" ] ... ²

São todos funcionalmente equivalentes em shells POSIX¹. O shell Bourne não tinha a palavra-chave ! , então não suportaria 3 acima e tinha todos os tipos de bugs com valores especiais de $var (como = , -n , ! ...) em todos, menos 7 ( muitos outros shells também tinham erros similares ).

Em uma veia semelhante, você pode (e deve) usar [ "$a" = "$b" ] && [ "$x" = "$y" ] no lugar de [ "$a" = "$b" -a "$x" = "$y" ] , sendo esta última obsoleta e não confiável.

O ! de 3 é um recurso de shell POSIX. Ele ainda faz sentido do utilitário test / [ para suportar seu próprio operador ! (como em 2/6) para outros shells ou aplicativos que não são shell que podem querer usá-lo e negar condições.

O utilitário test foi introduzido pelo Unix v7. Antes disso, havia um utilitário if que tinha ! , = , != , -a / -o , mas não -n / -z .

Suponho que -n / -z foram adicionados por conveniência ( test -n "$var" sendo um formato abreviado para test "$var" != '' e -z sendo adicionados para consistência)

¹ Tecnicamente, enquanto test / [ é construído virtualmente em todos os shells parecidos com o Bourne, isso não é obrigatório pelo POSIX e as primeiras versões do shell Bourne não o tinham embutido. Enquanto o shell Almquist sempre teve um test embutido, alguns BSDs não permitiram que alguns BSDs não tivessem um [ / test construído em sh até os anos 2000. Em qualquer caso, independentemente de um determinado shell ter um comando [ / test integrado, todos os sistemas POSIX também terão um comando [ / test no sistema de arquivos (que pode ou não se comportar o mesmo que o comando [ / test builtin de qualquer shell no sistema).

² Isso não quer dizer que são os únicos comandos que podem ser usados para testar se uma variável é a string vazia.

case $var in
  "") ...
esac

é uma maneira que não envolve a execução de nenhum comando.

expr "x$var" : 'x$' > /dev/null
${var:+"false"}
awk 'BEGIN{exit(ARGV[1] != "")}' "$var"
[ "${#var}" -eq 0 ]

São mais exemplos de maneiras complicadas de fazer isso.

Algumas shells semelhantes a Korn, como bash , também possuem algumas construções condicionais e aritméticas incorporadas que visam substituir o comando [ ( [[ -z $var ]] , ((${#var} == 0)) ...) .

    
por 14.06.2017 / 18:38