Existe uma diferença no bash ou um uso preferencial de negação de uma instrução?
if ! [[ -z "${var}" ]]; then
do_something
fi
Contra
if [[ ! -z "${var}" ]]; then
do_something
fi
Responder1
! [[ expression ]]
Isso será verdadeiro se todo o teste retornar falso
[[ ! expression ]]
Isso será verdadeiro se a expressão individual retornar falso.
Como o teste pode ser uma expressão composta, isso pode ser muito diferente. Por exemplo:
$ [[ ! 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
yes
$ ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
no
Pessoalmente, prefiro usar a negação dentro da construção de teste, quando aplicável, mas está perfeitamente bem fora, dependendo da sua intenção.
Responder2
A ! cmd
é na verdade umcanoe !
nega o código de saída dotodocano.
Do homem bash:
Pipelines Um pipeline é uma sequência de um ou mais comandos separados por um dos operadores de controle | ou |&. O formato de um pipeline é:
[time [-p]] [ ! ] command [ [|||&] command2 ... ]
...
Se a palavra reservada ! precede um pipeline, o status de saída desse pipeline é a negação lógica do status de saída conforme descrito acima. O shell aguarda que todos os comandos no pipeline sejam finalizados antes de retornar um valor.
Nesse sentido, um:
! [[ 2 -eq 2 ]]
É a negação ( !
) do código de saída do todo [[
(depois que tudo tiver sido executado). Portanto, este tem um código de saída 0:
! [[ 2 -eq 2 && 3 -eq 4 ]]
No entanto
Um [[ ! ]]
é umComando composto(não é um cano). Do homem bash:
Comandos compostos
...
[[ expressão ]]
Retorna um status de 0 ou 1 dependendo da avaliação da expressão condicional expressão.
As expressões são compostas pelas primárias descritas abaixo em EXPRESSÕES CONDICIONAIS.
Portanto, este tem um código de saída 1:
[[ ! 2 -eq 2 && 3 -eq 4 ]]
Porque isso é realmente equivalente a isto:
[[ ( ! 2 -eq 2 ) && ( 3 -eq 4 ) ]]
Que, por avaliação de curto-circuito, o lado direito do &&
nunca é avaliado e é na verdade equivalente a esta expressão muito mais curta:
[[ ! 2 -eq 2 ]]
O que sempre será falso (1).
Resumindo: dentro de [[
, o ! afetapeçasda expressão.
Preferido
Usar o !
inside [[
é muito mais comum (e portátil para mais shells (com [
)), mas às vezes pode ser confuso se não for explicitamente controlado pelo uso criterioso de ()
para delimitar a extensão da negação (o que pode se tornar um problema dentro [
das construções).
Mas (em bash, ksh e zsh) o resultado ! [[
é claramente definido e mais fácil de entender: execute o todo [[
e negue o resultado.
Qual deles deve ser usado é uma questão de preferência pessoal (e compreensão).