summaryrefslogtreecommitdiff
path: root/LINUX/BASH_github/bash-guide-2.md
diff options
context:
space:
mode:
authorvlapa <vlapa@ya.ru>2026-06-13 20:33:26 +0300
committervlapa <vlapa@ya.ru>2026-06-13 20:33:26 +0300
commite5abc1fe99340b979b18864d978179f71fe8f5c5 (patch)
tree98fd0ad7c6d0744894d6e74e446daacd9e6dd1b5 /LINUX/BASH_github/bash-guide-2.md
First
Diffstat (limited to 'LINUX/BASH_github/bash-guide-2.md')
-rw-r--r--LINUX/BASH_github/bash-guide-2.md225
1 files changed, 225 insertions, 0 deletions
diff --git a/LINUX/BASH_github/bash-guide-2.md b/LINUX/BASH_github/bash-guide-2.md
new file mode 100644
index 0000000..92c42fa
--- /dev/null
+++ b/LINUX/BASH_github/bash-guide-2.md
@@ -0,0 +1,225 @@
+# [Основы BASH. Часть 2](https://habr.com/post/52871/)
+
+## Циклы. Цикл 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