|
Поиск по сайту:
Главная
О проекте
Web-мастеру
HTML & JavaScript
SSI
Perl
PHP
XML & XSLT
Unix Shell
MySQL
Безопасность
Хостинг
Другое
|
|
Глава 8. Операции и смежные темы
8.1. Операторы
присваивание
- variable
assignment
-
Инициализация переменной или изменение ее
значения
- =
-
Универсальный оператор присваивания, пригоден как
для сравнения целых чисел, так и для сравнения
строк.
var=27
category=minerals # Пробелы до и после оператора "=" -- недопустимы.
|
Пусть вас не смущает, что оператор
присваивания ("="), по своему
внешнему виду, совпадает с оператором сравнения
(=).
# Здесь знак "=" выступает в качестве оператора сравнения
if [ "$string1" = "$string2" ]
# if [ "X$string1" = "X$string2" ] более отказоустойчивый вариант,
# предохраняет от "сваливания" по ошибке в случае, когда одна из переменных пуста.
# (добавленные символы "X" компенсируют друг друга.)
then
command
fi
|
арифметические
операторы
- +
-
сложение
- -
-
вычитание
- *
-
умножение
- /
-
деление
- **
-
возведение в степень
# В Bash, начиная с версии 2.02, был введен оператор возведения в степень -- "**".
let "z=5**3"
echo "z = $z" # z = 125
- %
-
модуль (деление по модулю), возвращает остаток от
деления
bash$ echo `expr 5 % 3`
2
Этот оператор может применяться в алгоритмах
генерации псевдослучайных чисел в заданном диапазоне
(см. Пример 9-23 и Пример 9-26), для форматирования
вывода на экран (см. Пример
25-15 и Пример A-7), и даже
для генерации простых чисел (см. Пример A-18). На удивление часто операцию
деления по модулю можно встретить в различных численных
алгоритмах.
Пример 8-1. Наибольший общий
делитель
#!/bin/bash
# gcd.sh: поиск наибольшего общего делителя
# по алгоритму Эвклида
# Под "наибольшим общим делителем" (нод) двух целых чисел
#+ понимается наибольшее целое число, которое делит оба делимых без остатка.
# Алгоритм Эвклида выполняет последовательное деление.
# В каждом цикле,
#+ делимое <--- делитель
#+ делитель <--- остаток
#+ до тех пор, пока остаток не станет равным нулю (остаток = 0).
#+ The gcd = dividend, on the final pass.
#
# Замечательное описание алгоритма Эвклида можно найти
# на сайте Jim Loy, http://www.jimloy.com/number/euclids.htm.
# ------------------------------------------------------
# Проверка входных параметров
ARGS=2
E_BADARGS=65
if [ $# -ne "$ARGS" ]
then
echo "Порядок использования: `basename $0` первое-число второе-число"
exit $E_BADARGS
fi
# ------------------------------------------------------
gcd ()
{
# Начальное присваивание.
dividend=$1 # В сущности, не имеет значения
divisor=$2 #+ какой из них больше.
# Почему?
remainder=1 # Если переменные неинициализировать,
#+ то работа сценария будет прервана по ошибке
#+ в первом же цикле.
until [ "$remainder" -eq 0 ]
do
let "remainder = $dividend % $divisor"
dividend=$divisor # Повторить цикл с новыми исходными данными
divisor=$remainder
done # алгоритм Эвклида
} # последнее $dividend и есть нод.
gcd $1 $2
echo; echo "НОД чисел $1 и $2 = $dividend"; echo
# Упражнение :
# --------
# Вставьте дополнительную проверку входных аргументов,
#+ и предусмотрите завершение работы сценария с сообщением об ошибке, если
#+ входные аргументы не являются целыми числами.
exit 0
- +=
-
"плюс-равно"
(увеличивает значение переменной на заданное число)
let "var +=
5" значение переменной var будет увеличено на 5.
- -=
-
"минус-равно"
(уменьшение значения переменной на заданное число)
- *=
-
"умножить-равно" (умножить
значение переменной на заданное число, результат
записать в переменную)
let "var *=
4" значение переменной var будет увеличено в 4 раза.
- /=
-
"слэш-равно"
(уменьшение значения переменной в заданное число
раз)
- %=
-
"процент-равно"
(найти остаток от деления значения переменной на
заданное число, результат записать в переменную)
Арифметические операторы очень часто
используются совместно с командами expr и let.
Пример 8-2. Арифметические
операции
#!/bin/bash
# От 1 до 6 пятью различными способами.
n=1; echo -n "$n "
let "n = $n + 1" # let "n = n + 1" тоже допустимо
echo -n "$n "
: $((n = $n + 1))
# оператор ":" обязателен, поскольку в противном случае, Bash будет
#+ интерпретировать выражение "$((n = $n + 1))" как команду.
echo -n "$n "
n=$(($n + 1))
echo -n "$n "
: $[ n = $n + 1 ]
# оператор ":" обязателен, поскольку в противном случае, Bash будет
#+ интерпретировать выражение "$[ n = $n + 1 ]" как команду.
# Не вызывает ошибки даже если "n" содержит строку.
echo -n "$n "
n=$[ $n + 1 ]
# Не вызывает ошибки даже если "n" содержит строку.
#* Старайтесь избегать употребления такой конструкции,
#+ поскольку она уже давно устарела и не переносима.
echo -n "$n "; echo
# Спасибо Stephane Chazelas.
exit 0
|
Целые числа в Bash фактически являются
длинными целыми (32-бит) со
знаком, с диапазоном изменений от -2147483648 до
2147483647. Если в результате какой либо операции эти
пределы будут превышены, то результат получится
ошибочным.
a=2147483646
echo "a = $a" # a = 2147483646
let "a+=1" # Увеличить "a" на 1.
echo "a = $a" # a = 2147483647
let "a+=1" # увеличить "a" еще раз, с выходом за границы диапазона.
echo "a = $a" # a = -2147483648
# ОШИБКА! (выход за границы диапазона)
Версия Bash 2.05b, поддерживает 64-ьитные целые
числа.
|
|
Bash ничего не знает о существовании чисел с
плавающей запятой. Такие числа, из-за наличия символа
десятичной точки, он воспринимает как строки.
a=1.5
let "b = $a + 1.3" # Ошибка.
# t2.sh: let: b = 1.5 + 1.3: syntax error in expression (error token is ".5 + 1.3")
echo "b = $b" # b=1
Для работы с числами с плавающей запятой в сценариях можно
использовать утилиту-калькулятор bc.
|
битовые
операции
- <<
-
сдвигает на 1 бит влево (умножение на 2)
- <<=
-
"сдвиг-влево-равно"
let "var
<<= 2" значение переменной
var сдвигается влево на 2 бита
(умножается на 4)
- >>
-
сдвиг вправо на 1 бит (деление на 2)
- >>=
-
"сдвиг-вправо-равно" (имеет
смысл обратный <<=)
- &
-
по-битовое И (AND)
- &=
-
"по-битовое
И-равно"
- |
-
по-битовое ИЛИ (OR)
- |=
-
"по-битовое
ИЛИ-равно"
- ~
-
по-битовая инверсия
- !
-
По-битовое отрицание
- ^
-
по-битовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR)
- ^=
-
"по-битовое
ИСКЛЮЧАЮЩЕЕ-ИЛИ-равно"
логические
операции
- &&
-
логическое И (and)
if [ $condition1 ] && [ $condition2 ]
# То же самое, что: if [ $condition1 -a $condition2 ]
# Возвращает true если оба операнда condition1 и condition2 истинны...
if [[ $condition1 && $condition2 ]] # То же верно
# Обратите внимание: оператор && не должен использоваться внутри [ ... ].
|
оператор &&, в зависимости от
контекста, может так же использоваться в
И-списках для
построения составных команд.
|
- ||
-
логическое ИЛИ (or)
if [ $condition1 ] || [ $condition2 ]
# То же самое, что: if [ $condition1 -o $condition2 ]
# Возвращает true если хотя бы один из операндов истинен...
if [[ $condition1 || $condition2 ]] # Also works.
# Обратите внимание: оператор || не должен использоваться внутри [ ... ].
|
Bash производит проверку кода возврата КАЖДОГО из
операндов в логических выражениях.
|
Пример 8-3. Построение сложных условий,
использующих && и ||
#!/bin/bash
a=24
b=47
if [ "$a" -eq 24 ] && [ "$b" -eq 47 ]
then
echo "Первая проверка прошла успешно."
else
echo "Первая проверка не прошла."
fi
# ОКА: if [ "$a" -eq 24 && "$b" -eq 47 ]
# пытается выполнить ' [ "$a" -eq 24 '
# и терпит неудачу наткнувшись на ']'.
#
# if [[ $a -eq 24 && $b -eq 24 ]] это правильный вариант
# (в строке 17 оператор "&&" имеет иной смысл, нежели в строке 6.)
# Спасибо Stephane Chazelas.
if [ "$a" -eq 98 ] || [ "$b" -eq 47 ]
then
echo "Вторая проверка прошла успешно."
else
echo "Вторая проверка не прошла."
fi
# Опции -a и -o предоставляют
#+ альтернативный механизм проверки условий.
# Спасибо Patrick Callahan.
if [ "$a" -eq 24 -a "$b" -eq 47 ]
then
echo "Третья проверка прошла успешно."
else
echo "Третья проверка не прошла."
fi
if [ "$a" -eq 98 -o "$b" -eq 47 ]
then
echo "Четвертая проверка прошла успешно."
else
echo "Четвертая проверка не прошла."
fi
a=rhino
b=crocodile
if [ "$a" = rhino ] && [ "$b" = crocodile ]
then
echo "Пятая проверка прошла успешно."
else
echo "Пятая проверка не прошла."
fi
exit 0
Операторы && и
|| могут использоваться и в
арифметических вычислениях.
bash$ echo $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0))
1 0 1 0
прочие
операции
- ,
-
запятая
С помощью оператора запятая можно связать несколько
арифметических в одну последовательность. При разборе
таких последовательностей, командный интерпретатор
вычисляет все выражения (которые могут иметь побочные
эффекты) в последовательности и возвращает результат
последнего.
let "t1 = ((5 + 3, 7 - 1, 15 - 4))"
echo "t1 = $t1" # t1 = 11
let "t2 = ((a = 9, 15 / 3))" # Выполняется присваивание "a" = 9,
#+ а затем вычисляется "t2".
echo "t2 = $t2 a = $a" # t2 = 5 a = 9
Оператор запятая чаще всего находит применение в
циклах for. См. Пример 10-12.
8.2.
Числовые константы
Интерпретатор командной
оболочки воспринимает числа как десятичные, в противном
случае числу должен предшествовать специальный префикс, либо
число должно быть записано в особой нотации. Числа,
начинающиеся с символа 0, считаются восьмеричными. если числу
предшествует префикс 0x, то число считается шестнадцатиричным. Число, в
записи которого присутствует символ #, расценивается как запись числа
с указанием основы счисления в виде ОСНОВА#ЧИСЛО.
Пример 8-4. Различные представления числовых
констант
#!/bin/bash
# numbers.sh: Различные представления числовых констант.
# Десятичное: по-умолчанию
let "dec = 32"
echo "десятичное число = $dec" # 32
# Вобщем-то ничего необычного.
# Восьмеричное: числа начинаются с '0' (нуля)
let "oct = 032"
echo "восьмеричное число = $oct" # 26
# Результат печатается в десятичном виде.
# --------- ------ -- -------
# Шестнадцатиричное: числа начинаются с '0x' или '0X'
let "hex = 0x32"
echo "шестнадцатиричное число = $hex" # 50
# Результат печатается в десятичном виде.
# Другие основы счисления: ОСНОВА#ЧИСЛО
# ОСНОВА должна быть между 2 и 64.
# для записи ЧИСЛА должен использоваться соответствующий ОСНОВЕ диапазон символов,
# см. ниже.
let "bin = 2#111100111001101"
echo "двоичное число = $bin" # 31181
let "b32 = 32#77"
echo "32-ричное число = $b32" # 231
let "b64 = 64#@_"
echo "64-ричное число = $b64" # 4094
#
# Нотация ОСНОВА#ЧИСЛО может использоваться на ограниченном
#+ диапазоне основ счисления (от 2 до 64)
# 10 цифр + 26 символов в нижнем регистре + 26 символов в верхнем регистре + @ + _
echo
echo $((36#zz)) $((2#10101010)) $((16#AF16)) $((53#1aA))
# 1295 170 44822 3375
# Важное замечание:
# --------------
# Использование символов, для записи числа, выходящих за диапазо,
#+ соответствующий ОСНОВЕ счисления
#+ будет приводить к появлению сообщений об ошибках.
let "bad_oct = 081"
# numbers.sh: let: oct = 081: value too great for base (error token is "081")
# Для записи восьмеричных чисел допускается использовать
#+ только цифры в диапазоне 0 - 7.
exit 0 # Спасибо Rich Bartell и Stephane Chazelas, за разъяснения.
Назад | Вперед
Содержание (общее) | Содержание раздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|
|
|