Простые логические операторы в Bash

У меня есть пара переменных, и я хочу проверить следующее условие (записано в словах, затем моя неудачная попытка с bash):

if varA EQUALS 1 AND ( varB EQUALS "t1" OR varB EQUALS "t2" ) then 

do something

done.

И в моей неудачной попытке я придумал:

if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) ); 
  then
    scale=0.05
  fi

Ответ 1

То, что вы написали, фактически почти работает (оно будет работать, если все переменные были числами), но это вовсе не идиоматический способ.

  • (…) круглые скобки обозначают subshell. Что внутри них не выражение, как на многих других языках. Это список команд (как и в скобках). Эти команды выполняются в отдельном подпроцессе, поэтому любое переадресация, назначение и т.д., Выполненные внутри круглых скобок, не имеют эффекта вне круглых скобок.
    • При знаке доллара, $(…) является подстановка команды: в скобках есть команда, а результат команды используется как часть командной строки (после дополнительных расширений, если замена не находится между двойными кавычками, а другая история).
  • { … } скобки подобны скобкам, поскольку они группируют команды, но они влияют только на синтаксический анализ, а не на группировку. Программа x=2; { x=4; }; echo $x печатает 4, тогда как x=2; (x=4); echo $x печатает 2. (Также скобки требуют пространства вокруг них и точки с запятой перед закрытием, тогда как в скобках нет. Это просто синтаксический причуда.)
    • При знаке доллара, ${VAR} является расширением параметра, расширяющимся до значения переменной с возможными дополнительными преобразованиями.
  • ((…)) двойные круглые скобки окружают арифметическую инструкцию, то есть вычисление по целым числам, с синтаксисом, напоминающим другие языки программирования. Этот синтаксис в основном используется для присвоений и в условных выражениях.
    • Тот же синтаксис используется в арифметических выражениях $((…)), которые расширяются до целочисленного значения выражения.
  • [[ … ]] двойные скобки окружают условные выражения. Условные выражения в основном построены на операторах, например -n $variable, чтобы проверить, является ли пустая переменная, и -e $file, чтобы проверить, существует ли файл. Существуют также операторы равенства строк: "$string1" = "$string2" (остерегайтесь того, что правая часть является шаблоном, например [[ $foo = a* ]], если $foo начинается с a, а [[ $foo = "a*" ]] проверяет, является ли $foo ровно a*) и знакомые операторы !, && и || для отрицания, конъюнкции и дизъюнкции, а также круглые скобки для группировки. Обратите внимание, что вам нужно пространство вокруг каждого оператора (например, [[ "$x" = "$y" ]], not [[ "$x"="$y" ]]) и пробел или символ типа ; как внутри, так и снаружи скобок (например, [[ -n $foo ]], не [[-n $foo]]).
  • [ … ] отдельные скобки являются альтернативной формой условных выражений с большим количеством причуд (но более старых и более переносимых). На данный момент не пишите; начните беспокоиться о них, когда найдете скрипты, содержащие их.

Это идиоматический способ написать тест в bash:

if [[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]; then

Если вам нужна переносимость для других оболочек, это будет так (обратите внимание на дополнительное цитирование и отдельные наборы скобок вокруг каждого отдельного теста):

if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then

Ответ 2

очень близко

if [[ $varA -eq 1 ]] && [[ $varB == 't1' || $varC == 't2' ]]; 
  then 
    scale=0.05
  fi

должен работать.

сломать его

[[ $varA -eq 1 ]] 

- целочисленное сравнение где as

$varB == 't1'

- сравнение строк. в противном случае я просто правильно группирую сравнения.

Двойные квадратные скобки ограничивают условное выражение. И я считаю следующее хорошее чтение по этому вопросу: "(IBM) Тест Demystify, [, [[, ((, и if-then- еще"

Ответ 3

Очень портативная версия (даже для старой оболочки bourne):

if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ] then 

  do something

fi

У этого есть дополнительное качество работы только одного подпроцесса максимум (который является процессом '['), независимо от вкуса оболочки.

Замените "=" на "-eq", если переменные содержат числовые значения, например

  • 3 -eq 03 истинно, но
  • 3 = 03 - false. (сравнение строк)

Ответ 4

if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
    echo STR is empty but should have a value.
fi