Логические операторы

Как мы узнали в главе 27, составная команда (( )) поддерживает разные операторы сравнения. Однако существует еще несколько операторов, которые можно использовать для оценки. Полный список приводится в табл. 34.5.

Таблица 34.5. Операторы сравнения

Оператор

Описание

<=

Меньше или равно

>=

Больше или равно

<

Меньше

>

Больше

==

Равно

!=

Не равно

&&

Логическое И (AND)

||

Логическое ИЛИ (OR)

выражение1?выражение2:выражение3

Тернарный (трехместный) оператор сравнения. Если выражение1 вернет ненулевое значение (арифметическую истину), будет выполнено выражение2, иначе — выражение3

При использовании логических операторов в арифметических выражениях действуют следующие правила: выражение, возвращающее 0, считается ложным, а выражение, возвращающее ненулевое значение, — истинным. Составная команда (( )) отображает результаты в обычные для командной оболочки коды завершения:

[me@linuxbox ~]$ if ((1)); then echo "true"; else echo "false"; fi

true

[me@linuxbox ~]$ if ((0)); then echo "true"; else echo "false"; fi

false

Самым странным из логических операторов выглядит тернарный (или трехместный) оператор. Этот оператор (заимствованный из языка программирования C) самостоятельно выполняет логическую проверку. Его можно использовать вместо инструкции if/then/else. Он оперирует тремя арифметическими выражениями (этот оператор не работает со строками), и если первое выражение оценивается как истинное (то есть возвращает ненулевое значение), выполняется второе выражение. Иначе выполняется третье выражение. Опробуем его в командной строке.

[me@linuxbox ~]$ a=0

[me@linuxbox ~]$ ((a<1?++a:--a))

[me@linuxbox ~]$ echo $a

1

[me@linuxbox ~]$ ((a<1?++a:--a))

[me@linuxbox ~]$ echo $a

0

Этот пример реализует переключение значения переменной. Каждый раз, когда выполняется оператор, значение переменной a переключается с 0 на 1 или обратно.

Обратите внимание, что прямое присваивание в этом операторе считается недопустимой операцией. Если попытаться выполнить присваивание, bash сообщит об ошибке:

[me@linuxbox ~]$ a=0

[me@linuxbox ~]$ ((a<1?a+=1:a-=1))

bash: ((: a<1?a+=1:a-=1: attempted assignment to non-variable (error token is "-=1")

Эту проблему можно решить, заключив выражения присваивания в круглые скобки:

[me@linuxbox ~]$ ((a<1?(a+=1):(a-=1)))

Далее приводится более полный пример использования арифметических операторов в сценарии, который выводит простую таблицу чисел:

#!/bin/bash

# arith-loop: сценарий для демонстрации арифметических операторов

finished=0

a=0

printf "a a**2 a**3 "

printf "= ==== ==== "

until ((finished)); do

b=$((a**2))

c=$((a**3))

printf "%d %d %d " $a $b $c

((a<10?++a:(finished=1)))

done

В этом сценарии мы реализовали цикл until, проверяющий значение переменной finished. Первоначально переменной присвоено значение 0 (арифметическая ложь). Цикл продолжается, пока эта переменная не получит ненулевое значение. Внутри цикла вычисляются квадрат и куб переменной-счетчика a. В конце цикла выполняется проверка значения этой переменной. Если оно меньше 10 (максимальное число итераций), она увеличивается на 1, иначе переменной finished присваивается значение 1, что превращает ее в арифметическую истину, и цикл завершается. Запустив сценарий, вы получите следующий результат:

[me@linuxbox ~]$ arith-loop

a a**2 a**3

= ==== ====

0 0 0

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000