A sintaxe da shell é altamente dependente do contexto. Isto é, o que uma coisa específica (como true
ou false
) significa depende muito de onde ela ocorre. Nos seus exemplos, false
tem três significados completamente diferentes: um comando, um valor de string e um nome de variável (inexistente) contendo um valor inteiro. Deixe-me percorrer os exemplos:
false
como um comando:
false; echo $? # prints "1"
if false; then echo "yep"; else echo "nope"; fi # prints "nope"
Existe um comando chamado "false" (geralmente / usr / bin / false, ou um bash builtin que faz a mesma coisa) que realmente não faz nada exceto sair com um status de falha. Como um status de saída, zero indica sucesso (que é uma espécie de verdade) e diferente de zero indica falha (que é meio falso). Este é o oposto da convenção mais usual zero = false, nonzero = true, mas para status de saída faz mais sentido.
false
como um valor de cadeia não interpretada:
if [[ false ]]; then echo "yep"; else echo "nope"; fi # prints "yep"
if [[ true ]]; then echo "yep"; else echo "nope"; fi # prints "yep"
if [[ wibble ]]; then echo "yep"; else echo "nope"; fi # prints "yep"
if [[ "this is a string" ]]; then echo "yep"; else echo "nope"; fi # prints "yep"
[[ false ]]; echo $? # prints "0" (=success)
[ false ]; echo $? # prints "0" (=success)
test false; echo $? # prints "0" (=success)
Em todos esses casos, o comando test
ou seu sinônimo [
ou a expressão condicional do bash [[ ]]
não obtiveram uma expressão, apenas uma única cadeia de caracteres, portanto, eles executam um teste muito simples: é uma cadeia de comprimento diferente de zero? "true", "false", "wibble", etc são todos de comprimento diferente de zero, então o comando / expressão é verdadeiro, portanto bem-sucedido. Compare com:
[[ "" ]]; echo $? # prints "1" (=failure), because the string is zero-length
[[ ]]; echo $? # prints "1" (=failure), because there isn't even a string
[ ]; echo $? # same
Note que test
e [
são comandos normais, e "false" (e "wibble" etc) é apenas um argumento para isso. [[ ]]
é um pouco da sintaxe bash que pode ser usada no lugar de um comando. Seus argumentos / conteúdos são analisados de forma diferente dos próprios nomes dos comandos.
false
como um nome de variável possível que pode conter um número inteiro:
if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi # prints "equal"
Este é um pouco mais estranho, e depende dos detalhes de como os [[ ]]
testes de bash para a igualdade numérica. Note-se que em [[ ]]
(e [ ]
e test
expressões), -eq
testes de igualdade numérica, e =
testes de igualdade string. Então, por exemplo, [[ 01 -eq 1 ]]
(porque 1 e 01 são numericamente iguais) é verdadeiro, mas [[ 01 = 1 ]]
é falso (porque eles não são a mesma string). No caso de [[ false -eq true ]]
, "true" e "false" não são valores inteiros, então o bash tenta convertê-los em inteiros tratando-os como nomes de variáveis (e esperando que as variáveis contenham valores inteiros). De fato, nenhum deles é definido como uma variável, então ambos avaliam a string vazia, que pode ser interpretada como o inteiro 0. Observe:
if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi # prints "equal"
if [[ false -eq 0 ]]; then echo "equal"; else echo "nope"; fi # prints "equal"
false=5
if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi # now prints "nope"
Note que a definição false
como variável não tem efeito em seus outros usos; quando usado como um comando, ele ainda sairá com o status 1, e quando usado como uma string, ele ainda será apenas "falso" (não "5").