Добавить в цитаты Настройки чтения

Страница 108 из 113

Поразрядный сдвиг влево. Сдвигает все биты в числе на один разряд влево

>>

Поразрядный сдвиг вправо. Сдвигает все биты в числе на один разряд вправо

&

Поразрядная операция И (AND). Выполняет операцию И над всеми битами двух чисел

|

Поразрядная операция ИЛИ (OR). Выполняет операцию ИЛИ над всеми битами двух чисел

^

Поразрядная операция ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR). Выполняет операцию ИСКЛЮЧАЮЩЕЕ ИЛИ над всеми битами двух чисел

Обратите внимание, что для всех битовых операторов, кроме поразрядного отрицания, существуют соответствующие операторы присваивания (например, <<=).

Ниже показано, как с использованием оператора поразрядного сдвига влево вывести список степеней 2:

[[email protected]/* */ ~]$ 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, считается ложным, а выражение, возвращающее ненулевое значение, — истинным. Составная команда (( )) отображает результаты в обычные для командной оболочки коды завершения:

[[email protected]/* */ ~]$ if ((1)); then echo "true"; else echo "false"; fi

true

[[email protected]/* */ ~]$ if ((0)); then echo "true"; else echo "false"; fi

false

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

[[email protected]/* */ ~]$ a=0

[[email protected]/* */ ~]$ ((a<1?++a:--a))

[[email protected]/* */ ~]$ echo $a

1

[[email protected]/* */ ~]$ ((a<1?++a:--a))

[[email protected]/* */ ~]$ echo $a

0

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

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

[[email protected]/* */ ~]$ a=0

[[email protected]/* */ ~]$ ((a<1?a+=1:a-=1))



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

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

[[email protected]/* */ ~]$ ((a<1?(a+=1):(a-=1)))

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

#!/bin/bash

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

finished=0

a=0

printf "ata**2ta**3n"

printf "=t====t====n"

until ((finished)); do

        b=$((a**2))

        c=$((a**3))

        printf "%dt%dt%dn" $a $b $c

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

done

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

[[email protected]/* */ ~]$ 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

bc — язык калькулятора для вычислений с произвольной точностью

Мы уже знаем, что командная оболочка поддерживает все виды арифметических вычислений с целыми числами, но как быть, если понадобится реализовать какие-нибудь вычисления из высшей математики или хотя бы просто задействовать вещественные числа? Ответ: никак. По крайней мере, средствами командной оболочки. Для подобных вычислений придется использовать внешнюю программу. Существует множество вариантов решения этой проблемы. Одно из них — использовать программы на встроенном Perl или AWK, но, к сожалению, описание этих языков выходит далеко за рамки данной книги.

Другое решение — использовать специализированную программу-калькулятор. В большинстве систем Linux имеется одна из таких программ — программа с именем bc.

Программа bc читает файл с исходным кодом на собственном языке, напоминающем язык C, и выполняет его. Сценарий на языке bc можно хранить в отдельном файле или передавать его на стандартный ввод программы. Язык bc поддерживает массу возможностей, включая переменные, циклы и функции, определяемые программистом. Мы не будем рассматривать программу bc во всех подробностях, а познакомимся лишь с некоторыми ее возможностями, чтобы вы могли получить общее представление. Неплохое описание программы bc можно найти на странице справочного руководства (man).

Начнем с простого примера. Напишем сценарий на языке bc, складывающий два числа — 2 и 2:

/* Очень простой сценарий на языке bc */

2 + 2

Первая строка сценария — это комментарий. Для оформления комментариев в языке bc используется тот же синтаксис, что и в языке программирования C. Комментарии могут размещаться в нескольких строках, начинаясь с пары символов /* и заканчиваясь парой */.

Применение bc

Сохраним сценарий, приведенный выше, в файле foo.bc, а затем выполним его, как показано ниже:

[[email protected]/* */ ~]$ bc foo.bc

bc 1.06.94

Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation,

Inc.

This is free software with ABSOLUTELY NO WARRANTY.

For details type `warranty'.

4

Приглядевшись, можно обнаружить результат в самом низу, после сообщения с информацией об авторских правах. Вывод этого сообщения можно подавить параметром -q (quiet — безмолвно).

bc также можно использовать в интерактивном режиме:

[[email protected]/* */ ~]$ bc -q

2 + 2

4

quit

В интерактивном режиме мы просто вводим выражения и сразу же получаем результат. Команда quit завершает интерактивный сеанс.

Кроме того, существует возможность передать сценарий на стандартный ввод программы bc:

[[email protected]/* */ ~]$ bc < foo.bc

4

Эта возможность позволяет передавать сценарии с использованием встроенных документов, встроенных строк и конвейеров. Ниже приводится пример со встроенной строкой: