Ответ 1
Без каких-либо операторов [[
проверяет только пустую переменную. Если это так, то считается ложным, иначе оно считается истинным. Содержимое переменных не имеет значения.
Я пытаюсь запустить блок кода, если для одного флага установлено значение 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]];
что не совсем то, что я хочу сделать. Итак, мой вопрос - это лучший способ сделать такие сравнения, и почему некоторые из тестовых случаев, которые я ожидал бы просто передать?
Спасибо!
Без каких-либо операторов [[
проверяет только пустую переменную. Если это так, то считается ложным, иначе оно считается истинным. Содержимое переменных не имеет значения.
Ваше понимание булевых в контексте оболочки неверно.
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
true
и false
оцениваются как строки;)
[[ $var ]]
является эквивалентом [[ -n $var ]]
, который проверяет, является ли $var
пустым или нет.
Тогда нет необходимости указывать переменные внутри [[
. См. это напоминание.
Наконец, здесь объясняется разница между &&
внутри скобок и вне.
Оболочка не имеет булевых переменных, как таковых. Однако есть команды с именем true
и false
, статус выхода которых равен 0 и 1 соответственно, поэтому их можно использовать аналогично логическим значениям.
var1=true
var2=false
if $var1 && ! $var2; then var2="something"; fi
Разница заключается в том, что вместо того, чтобы тестировать, если значение var1
установлено на истинное значение, вы расширяете его до имени команды, которая запускается и преуспевает. Аналогично, var2
расширяется до имени команды, которое запускается и выходит из строя, но поскольку оно имеет префикс с !
, статус выхода инвертируется для указания успеха.
(Обратите внимание, что в отличие от большинства языков программирования, статус выхода 0 указывает на успех, потому что, хотя большинство команд имеют один способ преуспеть, существует много разных способов, с помощью которых они могут потерпеть неудачу, поэтому различным ненулевым значениям могут быть присвоены разные значения.)
Ближе всего вы можете использовать функции вместо переменных, потому что вы можете использовать их статус возврата в условных выражениях.
$ 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
Надеюсь, что это поможет.