bash "si [falso];" devuelve verdadero en lugar de falso, ¿por qué?
¿Por qué aparece el siguiente resultado True
?
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
Esto siempre dará resultado True
aunque la condición parezca indicar lo contrario. Si quito los corchetes []
funciona, pero no entiendo por qué.
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 test
comando siempre tiene éxito. Para ejecutar realmente el comando, suéltelo [
.
if false; then
echo "True"
else
echo "False"
fi
Una introducción booleana rápida para Bash
La if
declaració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 test
declaración toma operadores y operandos como argumentos y devuelve un código de resultado en el mismo formato que if
. Un alias de la test
declaración es [
, que a menudo se usa if
para realizar comparaciones más complejas.
Las declaraciones true
y false
no 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 test
declaració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 if
o &&
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 if
y [
y true
son técnicamente "comandos" y no "declaraciones"; Esta es sólo una explicación funcional muy básica.
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
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