П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 4096 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 6757 раз(а).

Учебник HTML.
Просмотров 3717 раз(а).

Руководство по PHP5.
Просмотров 5991 раз(а).

Хостинг через призму DNS.
Просмотров 4809 раз(а).

Подборка текстов стандартных документов.
Просмотров 56244 раз(а).

Учебник PHP - Самоучитель
Просмотров 3702 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 8335 раз(а).

Внешние атаки...
Просмотров 4563 раз(а).

Учебник PHP.
Просмотров 3172 раз(а).

SSI в примерах.
Просмотров 175 раз(а).



 
 
| Добавить в избранное | Сделать стартовой | Помощь





Глава 8. Операции и смежные темы

8.1. Операторы

присваивание

variable assignment

Инициализация переменной или изменение ее значения

=

Универсальный оператор присваивания, пригоден как для сравнения целых чисел, так и для сравнения строк.

var=27
category=minerals  # Пробелы до и после оператора "=" -- недопустимы.


Caution

Пусть вас не смущает, что оператор присваивания ("="), по своему внешнему виду, совпадает с оператором сравнения (=).

#    Здесь знак "="  выступает в качестве оператора сравнения

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
Note

Целые числа в 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-ьитные целые числа.

Caution

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.

битовые операции. Битовые операции очень редко используются в сценариях командного интерпретатора. Их главное назначение, на мой взгляд, установка и проверка некоторых значений, читаемых из портов ввода-вывода и сокетов. "Битовые операции" гораздо более уместны в компилирующих языках программирования, таких как C и C++.

битовые операции

<<

сдвигает на 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 ]]    # То же верно
# Обратите внимание: оператор && не должен использоваться внутри [ ... ].


Note

оператор &&, в зависимости от контекста, может так же использоваться в И-списках для построения составных команд.

||

логическое ИЛИ (or)

if [ $condition1 ] || [ $condition2 ]
# То же самое, что:  if [ $condition1 -o $condition2 ]
# Возвращает true если хотя бы один из операндов истинен...

if [[ $condition1 || $condition2 ]]    # Also works.
# Обратите внимание: оператор || не должен использоваться внутри [ ... ].


Note

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, за разъяснения.

Назад | Вперед
Содержание (общее) | Содержание раздела



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту: