Простые логические операторы в 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

5 ответов

Решение

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

  • (…) круглые скобки обозначают подоболочку. То, что внутри них, не является выражением, как во многих других языках. Это список команд (как и вне скобок). Эти команды выполняются в отдельном подпроцессе, поэтому любое перенаправление, присваивание и т. Д., Выполняемые внутри скобок, не влияют за пределы скобок.
    • С ведущим знаком доллара, $(…) является подстановкой команды: в скобках есть команда, а вывод команды используется как часть командной строки (после дополнительных расширений, если подстановка не заключена в двойные кавычки, но это уже другая история).
  • { … } Скобки подобны скобкам в том смысле, что они группируют команды, но они влияют только на синтаксический анализ, а не на группировку. Программа 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" ]] не [[ "$x"="$y" ]]) и пробел или символ ; как внутри, так и снаружи скобок (например, [[ -n $foo ]] не [[-n $foo]]).
  • [ … ] одиночные скобки - это альтернативная форма условных выражений с большим количеством причуд (но более старых и более переносимых). Не пиши пока что; начать беспокоиться о них, когда вы найдете сценарии, которые их содержат.

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

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

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

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

Очень близко

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

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

ломая это

[[ $varA -eq 1 ]] 

целочисленное сравнение, где как

$varB == 't1'

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

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

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

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

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

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

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

Вот код для короткой версии оператора if-then-else:

( [ $a -eq 1 ] || [ $b -eq 2 ] ) && echo "ok" || echo "nok"

Обратите внимание на следующее:

  1. || а также && операнды внутри, если условие (т.е. между круглыми скобками) являются логическими операндами (или / и)

  2. || а также && операнды снаружи, если условие означает то / иначе

Практически в заявлении говорится:

если (a=1 или b=2), тогда "ок", иначе "нок"

if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
    echo STR is empty but should have a value.
fi
Другие вопросы по тегам