Командная строка Linux
Шрифт:
[me@linuxbox ~]$ foo=1
[me@linuxbox ~]$ echo $((foo++))
1
[me@linuxbox ~]$ echo $foo
2
Если присвоить переменной foo значение 1 и затем увеличить ее значение с помощью оператора ++, следующего за именем переменной, выражение вернет прежнее значение 1 переменной foo. Однако если вывести значение переменной второй раз, мы увидим увеличенное значение. Если поместить оператор ++ перед параметром, мы получим более ожидаемый результат:
[me@linuxbox ~]$ foo=1
[me@linuxbox ~]$ echo $((++foo))
2
[me@linuxbox ~]$ echo $foo
2
Для
Операторы ++ и -- часто используются совместно с циклами. Внесем некоторые улучшения в сценарий, демонстрирующий применение оператора деления по модулю, чтобы немного сократить его:
#!/bin/bash
# modulo2 : демонстрация оператора деления по модулю
for ((i = 0; i <= 20; ++i )); do
if (((i % 5) == 0 )); then
printf "<%d> " $i
else
printf "%d " $i
fi
done
printf "\n"
Битовые операции
Командной оболочкой поддерживается класс операторов, которые манипулируют числами не совсем обычным способом. Эти операторы действуют на уровне битов. Они применяются для выполнения некоторых низкоуровневых операций, часто связанных с установкой или чтением битовых флагов. Описание битовых операторов приводится в табл. 34.4.
Таблица 34.4. Битовые операторы
Оператор
Описание
~
Поразрядное отрицание. Изменяет значения всех битов в числе на противоположные
<<
Поразрядный сдвиг влево. Сдвигает все биты в числе на один разряд влево
>>
Поразрядный сдвиг вправо. Сдвигает все биты в числе на один разряд вправо
&
Поразрядная операция И (AND). Выполняет операцию И над всеми битами двух чисел
|
Поразрядная операция ИЛИ (OR). Выполняет операцию ИЛИ над всеми битами двух чисел
^
Поразрядная операция ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR). Выполняет операцию ИСКЛЮЧАЮЩЕЕ ИЛИ над всеми битами двух чисел
Обратите внимание, что для всех битовых операторов, кроме поразрядного отрицания, существуют соответствующие операторы присваивания (например, <<=).
Ниже показано, как с использованием оператора поразрядного сдвига влево вывести список степеней 2:
[me@linuxbox ~]$ for ((i=0;i<8;++i)); do echo $((1<<i)); done
1
2
4
8
16
32
64
128
Логические операторы
Как мы узнали в главе 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\ta**2\ta**3\n"
printf "=\t====\t====\n"
until ((finished)); do
b=$((a**2))
c=$((a**3))
printf "%d\t%d\t%d\n" $a $b $c
((a<10?++a:(finished=1)))
done
В этом сценарии мы реализовали цикл until, проверяющий значение переменной finished. Первоначально переменной присвоено значение 0 (арифметическая ложь). Цикл продолжается, пока эта переменная не получит ненулевое значение. Внутри цикла вычисляются квадрат и куб переменной-счетчика a. В конце цикла выполняется проверка значения этой переменной. Если оно меньше 10 (максимальное число итераций), она увеличивается на 1, иначе переменной finished присваивается значение 1, что превращает ее в арифметическую истину, и цикл завершается. Запустив сценарий, вы получите следующий результат: