Присваивание

Хотя на данном этапе это не очевидно, тем не менее арифметические выражения могут выполнять операцию присваивания. Мы уже выполняли присваивание много раз, хотя и в других контекстах. Каждый раз, передавая переменной число, мы выполняем присваивание. То же самое можно делать в арифметических выражениях:

[me@linuxbox ~]$ foo=

[me@linuxbox ~]$ echo $foo

[me@linuxbox ~]$ if (( foo = 5 ));then echo "It is true."; fi

It is true.

[me@linuxbox ~]$ echo $foo

5

В примере выше мы сначала присвоили переменной foo пустое значение и проверили, что она действительно получила пустое значение. Далее выполнили коман­ду if с составной командой (( foo = 5 )). Эта команда имеет два интересных аспекта: (1) она присваивает значение 5 переменной foo и (2) оценивает ее значение как истинное, потому что присваивание прошло успешно.

ПРИМЕЧАНИЕ

Важно запомнить значение оператора = в примере выше. Одиночный знак = выполняет присваивание: выражение foo = 5 говорит: «Сделать значение переменной foo равным 5». Двойной знак == определяет эквивалентность: выражение foo == 5 говорит: «Переменная foo равна 5?» Это обстоятельство может вызывать путаницу, потому что команда test интерпретирует одиночный знак = как оператор сравнения строк. Это еще одна причина предпочесть более современные составные команды [[ ]] и (( )) вместо test.

В дополнение к оператору = командная оболочка поддерживает еще несколько очень полезных операторов присваивания, перечисленных в табл. 34.3.

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

Форма записи

Описание

параметр = значение

Простое присваивание. Присваивает указанное значение указанному параметру

параметр += значение

Присваивание со сложением. Эквивалентно выражению параметр = параметр + значение

параметр -= значение

Присваивание с вычитанием. Эквивалентно выражению параметр = параметр - значение

параметр *= значение

Присваивание с умножением. Эквивалентно выражению параметр = параметр ? значение

параметр /= значение

Присваивание с целочисленным делением. Эквивалентно выражению параметр = параметр ? значение

параметр %= значение

Присваивание с делением по модулю. Эквивалентно выражению параметр = параметр % значение

параметр++

Постинкремент переменной. Эквивалентно выражению параметр = параметр + 1. (Но см. обсуждение ниже.)

параметр--

Постдекремент переменной. Эквивалентно выражению параметр = параметр - 1

++параметр

Преинкремент переменной. Эквивалентно выражению параметр = параметр + 1

--параметр

Предекремент переменной. Эквивалентно выражению параметр = параметр - 1

Эти операторы присваивания обеспечивают удобный и компактный способ записи многих арифметических вычислений. Особый интерес представляют операторы инкремента (++) и декремента (--), они увеличивают или уменьшают значение своего параметра на 1. Эти операторы заимствованы из языка программирования C и внедрены в несколько других языков программирования, включая bash.

Операторы инкремента и декремента могут находиться перед параметром или после него. Хотя в обоих случаях они увеличивают или уменьшают значение параметра на 1, тем не менее их местоположение играет важную роль. Если оператор помещается перед параметром, сначала выполняется операция инкремента (или декремента) и только потом возвращается измененное значение параметра. Если оператор помещается за параметром, операция выполняется после возврата значения. Такое поведение может показаться странным, но оно реализовано с умыслом. Взгляните на следующий пример:

[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 " "