Простые логические операторы в 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"
Обратите внимание на следующее:
||
а также&&
операнды внутри, если условие (т.е. между круглыми скобками) являются логическими операндами (или / и)||
а также&&
операнды снаружи, если условие означает то / иначе
Практически в заявлении говорится:
если (a=1 или b=2), тогда "ок", иначе "нок"
if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
echo STR is empty but should have a value.
fi