Como o bash testa 'falso'?


1
$ false
$ echo $?
1

$ if [[ false ]]; then echo 'do it'; fi
do it

$ test false && echo 'do it'
do it

$ COND=false
$ echo $COND
false
$ if [[ $COND -ne 0 ]]; then echo 'do it'; fi
$ if [[ $COND -ne true ]]; then echo 'do it'; fi

Isso é um absurdo IMO, o que estou faltando aqui?

- Atualização

Então, o seguinte é como vai:

$ COND=false
$ if ! $COND; then echo 'do it'; fi
do it
$ if $COND; then echo 'do it'; fi

Mas eu quero combinar $CONDcom outras expressões condicionais em uma expressão de teste maior (ou [[ {expr} && {expr} ]]). Então, quando $CONDé falso, não funciona dentro de uma [[ {expr} ]]maneira intuitiva. Parece que [[ {expr} ]]é um pouco enganador quando o que eu preciso é mais como:

$ COND=false
$ if ! $COND && test -d ${HOME}/bin ; then echo 'do it'; fi
do it

Respostas:


2

A sintaxe da shell é altamente dependente do contexto. Isto é, o que uma coisa específica (como trueou false) significa depende muito de onde ela ocorre. Nos seus exemplos, falsetem 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 testou 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 teste [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 testexpressões), -eqtestes 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 falsecomo 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").


1

Você não está executando o falsecomando, mas usando [[(semelhante aos comandos teste [builtin) para avaliar a expressão "false" e sem dar mais nada para avaliar, está fazendo isso:

string
-n string
Verdadeiro se o comprimento da string for diferente de zero.

Veja a seção EXPRESSÕES CONDICIONAIS man bashpara mais informações.

if não executar o comando dado, em seguida, examina seu status de saída.

[Referenciada cortesia a resposta de SO ]


Obrigado, também encontrei uma boa explicação em stackoverflow.com/questions/19670061/bash-if-false-returns-true/…
Darren Weber
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.