Основы BASH. Часть 2
Основы BASH. Часть 2.
Извиняюсь за такую большую задержку между статьями, но сессия дает о себе знать в самый неподходящий момент 🙂
Всем спасибо за замечания, критику и дополнения, которые были озвучены в комментариях к прошлой статье.
Эта часть, как и обещал, будет посвящена циклам, математическим операциям и использованию внешних команд.
Начнем.
Циклы. Цикл for-in.
Оператор for-in предназначен для поочередного обращения к значениям перечисленным в списке. Каждое значение поочередно в списке присваивается переменной.
Синтаксис следующий:
for переменная in список_значений
do
команды
done
Рассмотрим небольшой пример:
#!/bin/bash
for i in 0 1 2 3 4 #переменной $i будем поочередно присваивать значения от 0 до 4 включительно
do
echo «Console number is $i» >> /dev/pts/$i #Пишем в файл /dev/pts/$i(файл виртуального терминала) строку «Console number is $i»
done #цикл окончен
exit 0
После выполнения примера в первых 5 виртуальных консолях(терминалах) появится строка с её номером. В переменную $i поочередно подставляются значения из списка и в цикле идет работа со значением этой переменной
Циклы. Цикл while.
Цикл while сложнее цикла for-in и используется для повторения команд, пока какое-то выражение истинно( код возврата = 0).
Синтаксис оператора следующий:
while выражение или команда возвращающая код возврата
do
команды
done
Пример работы цикла рассмотрим на следующем примере:
#!/bin/bash
again=yes #присваиваем значение «yes» переменной again
while [ «$again» = «yes» ] #Будем выполнять цикл, пока $again будет равно «yes»
do
echo «Please enter a name:»
read name
echo «The name you entered is $name»
echo «Do you wish to continue?»
read again
done
echo «Bye-Bye»
ite@ite-desktop:~$ ./bash2_primer1.sh
Please enter a name:
ite
The name you entered is ite
Do you wish to continue?
yes
Please enter a name:
mihail
The name you entered is mihail
Do you wish to continue?
no
Bye-Bye
Как видим цикл выполняется до тех пор, пока мы не введем что-то отличное от «yes». Между do и done можно описывать любые структуры, операторы и т.п., все они будут выполнятся в цикле.Но следует быть осторожным с этим циклом, если вы запустите на выполнение в нём какую-либо команду, без изменения переменной выражения, вы можете попасть в бесконечный цикл.
Теперь об условии истинности. После while, как и в условном операторе if-then-else можно вставлять любое выражение или команду, которая возвращает код возврата, и цикл будет исполнятся до тех пор, пока код возврата = 0! Оператор «[» аналог команды test, которая проверяет истинность условия, которое ей передали.
Рассмотрим еще один пример, я взял его из книги Advanced Bash Scripting. Уж очень он мне понравился :), но я его немного упростил. В этом примере мы познакомимся с еще одним типом циклов UNTIL-DO. Эта практически полный аналог цикла WHILE-DO, только выполняется пока какое-то выражение ложно.
Вот пример:
#!/bin/bash
echo «Введите числитель: »
read dividend
echo «Введите знаменатель: »
read divisor
dnd=$dividend #мы будем изменять переменные dividend и divisor,
#сохраним их знания в других переменных, т.к. они нам
#понадобятся
dvs=$divisor
remainder=1
until [ «$remainder» -eq 0 ]
do
let «remainder = dividend % divisor»
dividend=$divisor
divisor=$remainder
done
echo «НОД чисел $dnd и $dvs = $dividend»
ite@ite-desktop:~$ ./bash2_primer3.sh
Введите числитель:
100
Введите знаменатель:
90
НОД чисел 100 и 90 = 10
Математические операции
Команда let.
Команда let производит арифметические операции над числами и переменными.
Рассмотрим небольшой пример, в котором мы производим некоторые вычисления над введенными числами:
#!/bin/bash
echo «Введите a: »
read a
echo «Введите b: »
read b
let «c = a + b» #сложение
echo «a+b= $c»
let «c = a / b» #деление
echo «a/b= $c»
let «c echo «c после сдвига на 2 разряда: $c»
let «c = a % b» # находит остаток от деления a на b
echo «$a / $b. остаток: $c »
ite@ite-desktop:~$ ./bash2_primer2.sh
Введите a:
123
Введите b:
12
a+b= 135
a/b= 10
c после сдвига на 2 разряда: 40
123 / 12. остаток: 3
Ну вот, как видите ничего сложного, список математических операций стандартный:
+ — сложение
— — вычитание
* — умножение
/ — деление
** — возведение в степень
% — модуль(деление по модулю), остаток от деления
let позволяет использовать сокращения арифметических команд, тем самым сокращая кол-во используемых переменных. Например: a = a+b эквивалентно a +=b и т.д
Работа с внешними программами при написании shell-скриптов
Перенаправление потоков.
В bash(как и многих других оболочках) есть встроенные файловые дескрипторы: 0 (stdin), 1 (stdout), 2 (stderr).
stdout — Стандартный вывод. Сюда попадает все что выводят программы
stdin — Стандартный ввод. Это все что набирает юзер в консоли
stderr — Стандартный вывод ошибок.
Для операций с этими дескрипторами, существуют специальные символы: > (перенаправление вывода), < (перенаправление ввода). Оперировать ими не сложно. Например:
записать в файл listing содержание текущего каталога (уже полезней)
Если есть необходимость дописывать в файл(при использовании «>» он заменятеся), необходимо вместо «>» использовать «>>»
после просьбы sudo ввести пароль, он возьмется из файла my_password, как будто вы его ввели с клавиатуры.
Если необходимо записать в файл только ошибки, которые могли возникнуть при работе программы, то можно использовать:
цифра 2 перед «>» означает что нужно перенаправлять все что попадет в дескриптор 2(stderr).
Если необходимо заставить stderr писать в stdout, то это можно можно след. образом:
символ «&» означает указатель на дескриптор 1(stdout)
(Поумолчанию stderr пишет на ту консоль, в котрой работает пользователь(вренее пишет на дисплей)).
2.Конвееры.
Конвеер — очень мощный инструмент для работы с консолью Bash. Синтаксис простой:
команда1 | команда 2 — означает, что вывод команды 1 передастся на ввод команде 2
Конвееры можно группировать в цепочки и выводить с помощью перенаправления в файл, например:
вывод команды ls -la передается команде grep, которая отбирает все строки, в которых встретится слово hash, и передает команде сортировке sort, которая пишет результат в файл sorting_list. Все довольно понятно и просто.
Чаще всего скрипты на Bash используются в качестве автоматизации каких-то рутинных операций в консоли, отсюда иногда возникает необходимость в обработке stdout одной команды и передача на stdin другой команде, при этом результат выполнения одной команды должен быть неким образом обработан. В этом разделе я постораюсь объяснить основные принципы работы с внешними командами внутри скрипта. Думаю что примеров я привел достаточно и можно теперь писать только основные моменты.
1. Передача вывода в переменную.
Для того чтобы записать в переменную вывод какой-либо команды, достаточно заключить команду в « ковычки, например
Однако если вы захотите записать в переменную список директорий, то необходимо, должным образом обработать результат для помещения данных в переменную. Рассмотрим небольшой, пример:
LIST=`find /svn/ -type d 2>/dev/null| awk ‘ ‘| sort|uniq | tr ‘\n’ ‘ ‘`
for ONE_OF_LIST in $LIST
do
svnadmin hotcopy /svn/$ONE_OF_LIST /svn/temp4backup/$ONE_OF_LIST
done
Здесь мы используем цикл for-do-done для архивирование всех директорий в папке /svn/ с помощью команды svnadmin hotcopy(что в нашем случае не имеет никого значения, просто как пример). Наибольшй интерес вызывает строка: LIST=`find /svn/ -type d 2>/dev/null| awk ‘ ‘| sort|uniq | tr ‘\n’ ‘ ‘` В ней переменной LIST присваивается выполнение команды find, обработанной командами awk, sort, uniq,tr(все эти команды мы рассматривать не будем, ибо это отдельная статья). В переменной LIST будут имена всех каталогов в папке /svn/ пгомещенных в одну строку(для того чтобы её стравить циклу.
Как видно, все не сложно, достаточно понять принцип и написать пару своих скриптов. В заключении статьи хочу пожелать удачи в изучении BASH и Linux в целом. Критика, как водится приветствуется. Следующая статья возможно будет посвещена использованию таких программ как sed, awk.
Арифметические операции в Bash скрипте
let это встроенная функция bash, которая позволяет производить базовые арифметические операции.
Используется следующим образом:
Рассмотрим примеры в скрипте let_example.sh
#!/bin/bash # Простая арифметика с let let A=5+4 echo $A # 9 let «A = 5 + 4» echo $A # 9 let A++ echo $A # 10 let «A = 4 * 5» echo $A # 20 let «A = $1 + 30» echo $A # 30 + первый аргумент из командной строки
Разберём команды по очереди:
Строка 4 — Это простейшая форма записи без кавычек.
Помните, что если вычисление идёт без кавычек — ставить пробелы нельзя
Строка 7 — Если поставить кавычки — можно пользоваться пробелом для лучшей читаемости.\
Строка 10 — Увеличиваем значение на 1. Это аналог «a = a + 1».
Строка 16 — В выражение можно включить и другие переменные.
Таблица основных операторов
expr
expr похож на let за исключением того, что вместо сохранения результата в переменную expr по умолчанию печатает ответ.
Но никто не запрещает сохранять результат expr в переменные с помощью command substitution: x = $(expr 2 + 2)
В отличие от let не нужно заключать выражения с пробелами в кавычки
Нужно ставить пробелы вокруг операторов.
expr item1 operator item2
Рассмотрим простой пример:
#!/bin/bash # Простая арифметика с использованием expr expr 5 + 4 expr «5 + 4» expr 5+4 expr 5 \* $1 expr 11 % 2 A= $( expr 10 — 3 ) echo $A # 7
Разберём этот пример пошагово:
Строка 4 — Это базовый синтаксис. Обратите внимание на пробелы и на отсутствие кавычек.
Строка 6 — Если заключить выражение в кавычки его в таком виде и выведет в терминал.
Строка 8 — Если не поставить пробелы выражение будет выведено в терминал без вычисления.
Строка 10 — Некоторые символы нужно экранировать.
Строка 12 — Это деление по модулю. Результатом будет остаток от целочисленного деления двух чисел.
Строка 14 — Пример выполнения command substitution чтобы сохранить результат в переменную a.
Двойные скобки
Результат выполнения команды можно легко сохранить в переменную.
На основе этого механизма можно выполнять арифметические действия. Достаточно вместо одной пары скобок использовать две.
Рассмотрим примеры в скрипте
#!/bin/bash # Простая арифметика с двойными скобками A= $(( 4 + 5 )) echo $A # 9 A= $((3+5)) echo $A # 8 B= $(( A + 3 )) echo $B # 11 B= $(( $A + 4 )) echo $B # 12 (( B++ )) echo $B # 13 (( B += 3 )) echo $B # 16 A= $(( 4 * 5 )) echo $A # 20
Строка 4 — Базовый синтаксис. Можно ставить пробелы без использования кавычек.
Строка 7 — Работает и без пробелов.
Строка 10 — Можно использовать переменные без $ перед ними.
Строка 16 — Увеличение переменной на 1. Символ $ не нужен.
Строка 19 — Увеличение переменной на 3. Это краткая форма записи b = b + 3.
Строка 19 — В отличие от других способов символ * не нужно экранировать.
Двойные скобки дают довольно много свободы в форматировании кода.
Они доступны в Bash по умолчанию и их эффективность немного выше. Хотя заметить разницу на современных компьютерах будет непросто.
Сложение
Сложение в bash можно выполнить следущими способами
#!/bin/bash # Bash + # let A=2 B=3 let C=$A+ $B echo $C
#!/bin/bash # Bash + # expr and (( )) D=4 E=5 F=$( expr $D + $E ) G=$(( $D + $D )) echo $F echo $G
Целочисленное деление
В bash по умолчанию реализовано именно целочисленное деление
Рассмотрим, что будет если попытаться поделить числа с помощью let
#!/bin/bash # Целочисленное деление A=100 B=3 let «C = $A / $B » echo «C: $C «
Если вас это не устраивает — используйте bc
Остаток от деления
Остаток от деления можно получить с помощью % следующим оригинальным образом
Float Сложение
Сложение чисел с плавающей точкой можно выполнить с помощью bc
bc
В bash нет родной поддержки деления чисел с плавающей точкой. Но есть утилиты, которые умеют это делать.
Что будет если попытаться поделить числа с помощью let
#!/bin/bash # Деление с let A=100 B=3 let «C = $A / $B » echo «C: $C «
Чтобы этого не произошло используйте bc
bc: float умножение
Также с помощью bc удобно умножать числа с плавающей запятой