Bash, если [false]; возвращает true
Обучался bash на этой неделе и столкнулся с проблемой.
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
Это всегда будет выводить True, даже если условие, как представляется, указывает на другое. Если я удалю скобки []
, тогда он будет работать, но я не понимаю, почему.
Ответы
Ответ 1
Вы выполняете команду [
(aka test
) с аргументом "false", а не выполняете команду false
. Поскольку "false" является непустой строкой, команда test
всегда выполняется успешно. Чтобы выполнить команду, отпустите команду [
.
if false; then
echo "True"
else
echo "False"
fi
Ответ 2
Я обнаружил, что могу сделать базовую логику, выполнив что-то вроде:
A=true
B=true
if ($A && $B); then
C=true
else
C=false
fi
echo $C
Ответ 3
Использование true/false удаляет некоторый беспорядочный беспорядок...
#! /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
Ответ 4
Быстрый булевский грунт для Bash
Оператор if
принимает команду как аргумент (как и &&
, ||
и т.д.). Integer результирующий код команды интерпретируется как логический (0/null = true, 1/else = false).
Оператор test
принимает операторы и операнды в качестве аргументов и возвращает код результата в том же формате, что и if
. Алиасом оператора test
является [
, который часто используется с if
для выполнения более сложных сравнений.
Операторы true
и false
ничего не делают и возвращают код результата (0 и 1 соответственно). Поэтому они могут использоваться в качестве булевых литералов в Bash. Но если вы помещаете утверждения в место, где они интерпретируются как строки, вы столкнетесь с проблемами. В вашем случае:
if [ foo ]; then ... # "if the string 'foo' is non-empty, return true"
if foo; then ... # "if the command foo succeeds, return true"
Итак:
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;
Это похоже на выполнение чего-то вроде echo '$foo'
vs. echo "$foo"
.
При использовании оператора test
результат зависит от используемых операторов.
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)
Короче, если вы просто хотите что-то проверить как pass/fail (aka "true" / "false" ), затем передайте команду своим if
или &&
и т.д. без скобок. Для сложных сравнений используйте скобки с соответствующими операторами.
И да, я знаю, что в Bash нет такой вещи, как собственный булев тип, и что if
и [
и true
являются технически "командами", а не "заявления"; это просто базовое, функциональное объяснение.