Простые логические операторы в Bash - PullRequest
212 голосов
/ 07 июня 2011

У меня есть пара переменных, и я хочу проверить следующее условие (записанное словами, затем моя неудачная попытка сценария 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 ]

591 голосов
/ 07 июня 2011

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

  • (…) круглые скобки указывают подоболочка .То, что внутри них, не является выражением, как во многих других языках.Это список команд (как и в скобках).Эти команды выполняются в отдельном подпроцессе, поэтому любое перенаправление, присваивание и т. Д., Выполняемые внутри скобок, не влияют за пределы скобок.
    • С начальным знаком доллара $(…) является подстановкой команды : в скобках есть команда, а вывод команды используется как часть командной строки (последополнительные расширения, если подстановка не заключена в двойные кавычки, но это другая история ).
  • { … } фигурные скобки подобны скобкам в том, что они группируют команды, но они толькоВлияние парсинга, а не группировки.Программа 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
32 голосов
/ 07 июня 2011

очень близко

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

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

ломая его

[[ $varA -eq 1 ]] 

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

$varB == 't1'

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

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

6 голосов
/ 09 марта 2017

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

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

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

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

  • 3-экв 03 верно, но
  • 3 = 03 неверно. (сравнение строк)
1 голос
/ 15 марта 2018

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

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

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

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

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

На практике это утверждение гласит:

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

0 голосов
/ 30 июля 2015
if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
    echo STR is empty but should have a value.
fi
...