web-dev-qa-db-fra.com

Bash si [faux]; retourne vrai

Apprenez bash cette semaine et a rencontré un problème. 

#!/bin/sh

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

Cela produira toujours True même si la condition semble indiquer le contraire. Si je supprime les crochets [] alors cela fonctionne, mais je ne comprends pas pourquoi.

94
tenmiles

Vous exécutez la commande [ (ou test) avec l'argument "false", mais pas la commande false. Puisque "false" est une chaîne non vide, la commande test réussit toujours. Pour exécuter la commande, supprimez la commande [.

if false; then
   echo "True"
else
   echo "False"
fi
128
chepner

Un rapide amorce booléenne pour Bash

L'instruction if prend une commande en tant qu'argument (comme le font &&, ||, etc.). Le code de résultat entier de la commande est interprété comme un booléen (0/null = true, 1/else = false). 

L'instruction test prend les opérateurs et les opérandes comme arguments et renvoie un code de résultat au même format que if. Un alias de l'instruction test est [, qui est souvent utilisé avec if pour effectuer des comparaisons plus complexes.

Les instructions true et false ne font rien et renvoient un code résultat (0 et 1, respectivement). Ils peuvent donc être utilisés comme littéraux booléens dans Bash. Mais si vous placez les instructions à un endroit où elles sont interprétées comme des chaînes, vous rencontrerez des problèmes. Dans ton cas:

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

Alors:

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;

Ceci est similaire à quelque chose comme echo '$foo' vs echo "$foo".

Lorsque vous utilisez l'instruction test, le résultat dépend des opérateurs utilisés.

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 bref , si vous voulez simplement tester quelque chose comme succès/échec (ou "vrai"/"faux"), passez une commande à votre instruction if ou && etc., sans crochets. Pour les comparaisons complexes, utilisez des crochets avec les opérateurs appropriés.

Et oui, je sais qu’un type booléen natif n’existe pas dans Bash et que if, [ et true sont techniquement des "commandes" et non des "instructions"; ceci est juste une explication très basique et fonctionnelle.

15
Beejor

J'ai découvert que je pouvais faire une logique de base en exécutant quelque chose comme:

A=true
B=true
if ($A && $B); then
    C=true
else
    C=false
fi
echo $C
2
Rodrigo

L'utilisation de true/false supprime un peu d'encombrement des crochets ...

#! /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
0
psh