From e5abc1fe99340b979b18864d978179f71fe8f5c5 Mon Sep 17 00:00:00 2001 From: vlapa Date: Sat, 13 Jun 2026 20:33:26 +0300 Subject: First --- ... \320\247\320\260\321\201\321\202\321\214 2.md" | 223 +++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 "LINUX/BASH_script/BASH. \320\247\320\260\321\201\321\202\321\214 2.md" (limited to 'LINUX/BASH_script/BASH. Часть 2.md') diff --git "a/LINUX/BASH_script/BASH. \320\247\320\260\321\201\321\202\321\214 2.md" "b/LINUX/BASH_script/BASH. \320\247\320\260\321\201\321\202\321\214 2.md" new file mode 100644 index 0000000..dea8c45 --- /dev/null +++ "b/LINUX/BASH_script/BASH. \320\247\320\260\321\201\321\202\321\214 2.md" @@ -0,0 +1,223 @@ +## Циклы. Цикл 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 <<= 2" #сдвигает c на 2 разряда влево +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` — Стандартный вывод ошибок. +Для операций с этими дескрипторами, существуют специальные символы: `>` (перенаправление вывода), `<` (перенаправление ввода). Оперировать ими не сложно. Например: + +``` +cat /dev/random > /dev/null #перенаправить вывод команды cat /dev/random в /dev/null (абсолютно бесполезная операция :)) ) +``` +или + +``` +ls -la > listing #записать в файл listing содержание текущего каталога (уже полезней) +``` + +Если есть необходимость дописывать в файл(при использовании "`>`" он заменятеся), необходимо вместо "`>`" использовать "`>>`" +``` +sudo < my_password +``` +после просьбы sudo ввести пароль, он возьмется из файла my_password, как будто вы его ввели с клавиатуры. +Если необходимо записать в файл только ошибки, которые могли возникнуть при работе программы, то можно использовать: +``` +./program_with_error 2> error_file +``` +цифра 2 перед "`>`" означает что нужно перенаправлять все что попадет в дескриптор 2(stderr). +Если необходимо заставить `stderr` писать в `stdout`, то это можно след. образом: +``` +./program_with_error 2>&1 +``` +символ "`&`" означает указатель на дескриптор `1(stdout)` +(Поумолчанию `stderr` пишет на ту консоль, в котрой работает пользователь(вренее пишет на дисплей)). + +### 2. Конвееры. + +Конвеер — очень мощный инструмент для работы с консолью Bash. Синтаксис простой: +`команда1 | команда 2` — означает, что вывод команды 1 передастся на ввод команде 2 +Конвееры можно группировать в цепочки и выводить с помощью перенаправления в файл, например: +``` +ls -la | grep «hash» |sort > sortilg_list +``` +вывод команды `ls -la` передается команде `grep`, которая отбирает все строки, в которых встретится слово *hash*, и передает команде сортировке `sort`, которая пишет результат в файл *sorting_list*. Все довольно понятно и просто. + +Чаще всего скрипты на Bash используются в качестве автоматизации каких-то рутинных операций в консоли, отсюда иногда возникает необходимость в обработке `stdout` одной команды и передача на `stdin` другой команде, при этом результат выполнения одной команды должен быть неким образом обработан. В этом разделе я постораюсь объяснить основные принципы работы с внешними командами внутри скрипта. Думаю что примеров я привел достаточно и можно теперь писать только основные моменты. + +### 1. Передача вывода в переменную. + +Для того чтобы записать в переменную вывод какой-либо команды, достаточно заключить команду в ` `` ` ковычки, например +> a = \` echo "qwerty" \` +> echo $a + +Результат работы: qwerty + +Однако если вы захотите записать в переменную список директорий, то необходимо, должным образом обработать результат для помещения данных в переменную. Рассмотрим небольшой, пример: +``` +LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| 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 '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '` В ней переменной LIST присваивается выполнение команды find, обработанной командами awk, sort, uniq,tr(все эти команды мы рассматривать не будем, ибо это отдельная статья). В переменной LIST будут имена всех каталогов в папке /svn/ пгомещенных в одну строку(для того чтобы её стравить циклу. \ No newline at end of file -- cgit v1.2.3