Подтвердить что ты не робот

Bash Булевое тестирование

Я пытаюсь запустить блок кода, если для одного флага установлено значение true, а другое - false. то есть

var1=true
var2=false
if [[ $var1 && ! $var2 ]]; then var2="something"; fi

Поскольку это не оценивало то, что я ожидал, я написал несколько других тестовых примеров, и мне сложно понять, как они оцениваются.

aa=true 
bb=false
cc="python"
if [[ "$aa" ]]; then echo "Test0" ; fi
if [[ "$bb" ]]; then echo "Test0.1" ; fi
if [[ !"$aa" ]]; then echo "Test0.2" ; fi
if [[ ! "$aa" ]]; then echo "Test0.3" ; fi
if [[ "$aa" && ! "$bb" ]]; then echo "Test1" ; fi
if [[ "$aa" && ! "$aa" ]]; then echo "Test2" ; fi
if [[ "$aa" ]] && ! [[ "$bb" ]]; then echo "test3" ; fi
if [[ "$aa" ]] && ! [[ "$cc" ]]; then echo "test4" ; fi
if [[ $aa && ! $bb ]]; then echo "Test5" ; fi
if [[ $aa && ! $aa ]]; then echo "Test6" ; fi
if [[ $aa ]] && ! [[ $bb ]]; then echo "test7" ; fi
if [[ $aa ]] && ! [[ $cc ]]; then echo "test8" ; fi

Когда я запускаю предыдущий кодовый блок, единственным выходом, который я получаю, является

test0
Test0.1
Test0.2

однако, я ожидаю, что я получу

test0
Test1
Test3
test5
Test7

Я попытался понять лучший способ запуска подобных тестов, однако большинство примеров, которые я нашел, настроены в формате   if [[ "$ aa" == true]];
что не совсем то, что я хочу сделать. Итак, мой вопрос - это лучший способ сделать такие сравнения, и почему некоторые из тестовых случаев, которые я ожидал бы просто передать?

Спасибо!

4b9b3361

Ответ 1

Без каких-либо операторов [[ проверяет только пустую переменную. Если это так, то считается ложным, иначе оно считается истинным. Содержимое переменных не имеет значения.

Ответ 2

Ваше понимание булевых в контексте оболочки неверно.

var1=true
var2=false

Обе приведенные выше переменные являются истинными, так как это непустые строки.

Вместо этого вы можете использовать арифметический контекст:

$ a=1
$ b=0
$ ((a==1 && b==0)) && echo y
y
$ ((a==0 && b==0)) && echo y
$
$ ((a && !(b))) && echo y;       # This seems to be analogous to what you were attempting
y

Ответ 4

Оболочка не имеет булевых переменных, как таковых. Однако есть команды с именем true и false, статус выхода которых равен 0 и 1 соответственно, поэтому их можно использовать аналогично логическим значениям.

var1=true
var2=false
if $var1 && ! $var2; then var2="something"; fi

Разница заключается в том, что вместо того, чтобы тестировать, если значение var1 установлено на истинное значение, вы расширяете его до имени команды, которая запускается и преуспевает. Аналогично, var2 расширяется до имени команды, которое запускается и выходит из строя, но поскольку оно имеет префикс с !, статус выхода инвертируется для указания успеха.

(Обратите внимание, что в отличие от большинства языков программирования, статус выхода 0 указывает на успех, потому что, хотя большинство команд имеют один способ преуспеть, существует много разных способов, с помощью которых они могут потерпеть неудачу, поэтому различным ненулевым значениям могут быть присвоены разные значения.)

Ответ 5

Ближе всего вы можете использовать функции вместо переменных, потому что вы можете использовать их статус возврата в условных выражениях.

$  var1() { return 0; }
$  var2() { return 1; }  # !0 = failure ~ false

и мы можем протестировать этот путь

$  var1 && echo "it true" || echo "it false"
it true
$  var2 && echo "it true" || echo "it false"
it false

или таким образом

$  if var1; then echo "it true"; else echo "it false"; fi
it true
$  if var2; then echo "it true"; else echo "it false"; fi
it false

Надеюсь, что это поможет.