bash "si [falso];" devuelve verdadero en lugar de falso, ¿por qué?

Resuelto tenmiles asked hace 11 años • 6 respuestas

¿Por qué aparece el siguiente resultado True?

#!/bin/sh

if [ false ]; then
    echo "True"
else
    echo "False"
fi

Esto siempre dará resultado Trueaunque la condición parezca indicar lo contrario. Si quito los corchetes []funciona, pero no entiendo por qué.

tenmiles avatar Oct 30 '13 05:10 tenmiles
Aceptado

Está ejecutando el comando [(también conocido como test) con el argumento "falso", no ejecutando el comando false. Dado que "falso" es una cadena que no está vacía, el testcomando siempre tiene éxito. Para ejecutar realmente el comando, suéltelo [.

if false; then
   echo "True"
else
   echo "False"
fi
chepner avatar Oct 29 '2013 22:10 chepner

Una introducción booleana rápida para Bash

La ifdeclaración toma un comando como argumento (como hacer &&, ||etc.). El código de resultado entero del comando se interpreta como booleano (0/null=true, 1/else=false).

La testdeclaración toma operadores y operandos como argumentos y devuelve un código de resultado en el mismo formato que if. Un alias de la testdeclaración es [, que a menudo se usa ifpara realizar comparaciones más complejas.

Las declaraciones truey falseno hacen nada y devuelven un código de resultado (0 y 1, respectivamente). Por lo que pueden usarse como literales booleanos en Bash. Pero si coloca las declaraciones en un lugar donde se interpretan como cadenas, tendrá problemas. En tu caso:

if [ foo ]; then ... # "if the string 'foo' is non-empty, return true"
if foo; then ...     # "if the command foo succeeds, return true"

Entonces:

if [ true  ] ; then echo "This text will always appear." ; fi;
if [ false ] ; then echo "This text will always appear." ; fi;
if true      ; then echo "This text will always appear." ; fi;
if false     ; then echo "This text will never appear."  ; fi;

Esto es similar a hacer algo como echo '$foo'vs.echo "$foo"

Al utilizar la testdeclaración, el resultado depende de los operadores utilizados.

if [ "$foo" = "$bar" ]   # true if the string values of $foo and $bar are equal
if [ "$foo" -eq "$bar" ] # true if the integer values of $foo and $bar are equal
if [ -f "$foo" ]         # true if $foo is a file that exists (by path)
if [ "$foo" ]            # true if $foo evaluates to a non-empty string
if foo                   # true if foo, as a command/subroutine,
                         # evaluates to true/success (returns 0 or null)

En resumen , si solo desea probar algo como pasa/falla (también conocido como "verdadero"/"falso"), pase un comando a su declaración ifo &&etc., sin corchetes. Para comparaciones complejas, utilice corchetes con los operadores adecuados.

Y sí, soy consciente de que no existe un tipo booleano nativo en Bash, y que ify [y trueson técnicamente "comandos" y no "declaraciones"; Esta es sólo una explicación funcional muy básica.

Beejor avatar Dec 18 '2017 20:12 Beejor

Descubrí que puedo hacer algo de lógica básica ejecutando algo como:

A=true
B=true
if ($A && $B); then
    C=true
else
    C=false
fi
echo $C
Rodrigo avatar Jan 24 '2017 06:01 Rodrigo

El uso de verdadero/falso elimina parte del desorden de corchetes...

#! /bin/bash    
#  true_or_false.bash

[ "$(basename $0)" == "bash" ] && sourced=true || sourced=false

$sourced && echo "SOURCED"
$sourced || echo "CALLED"

# Just an alternate way:
! $sourced  &&  echo "CALLED " ||  echo "SOURCED"

$sourced && return || exit
psh avatar Nov 07 '2017 13:11 psh