summaryrefslogtreecommitdiffhomepage
path: root/ru-ru/bash-ru.html.markdown
blob: f8b282942f2f3d280d4a1fd0b3a380fd0aac2073 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
---
category: tool
tool: bash
contributors:
    - ["Max Yankov", "https://github.com/golergka"]
    - ["Darren Lin", "https://github.com/CogBear"]
    - ["Alexandre Medeiros", "http://alemedeiros.sdf.org"]
    - ["Denis Arh", "https://github.com/darh"]
    - ["akirahirose", "https://twitter.com/akirahirose"]
    - ["Anton Strömkvist", "http://lutic.org/"]
    - ["Rahil Momin", "https://github.com/iamrahil"]
    - ["Gregrory Kielian", "https://github.com/gskielian"]
    - ["Etan Reisner", "https://github.com/deryni"]
filename: LearnBash.sh
---

Bash это командная оболочка unix (unix shell), которая распространяется как оболочка для операционной системы GNU и используется в качестве оболочки по умолчанию для Linux и Mac OS X.
Почти все нижеприведенные примеры могут могут быть частью shell-скриптов или быть исполнены напрямую в shell.

[Подробнее.](http://www.gnu.org/software/bash/manual/bashref.html)

```bash
#!/bin/bash
# Первая строка скрипта - это shebang, который сообщает системе как исполнять
# этот скрипт: http://en.wikipedia.org/wiki/Shebang_(Unix)
# Как вы уже поняли, комментарии начинаются с #. Shebang — тоже коммантарий.

# Простой пример hello world:
echo Hello world!

# Отдельные команды начинаются с новой строки или разделяются точкой с запятой:
echo 'Это первая строка'; echo 'Это вторая строка'

# Вот так объявляется пемеренная:
VARIABLE="Просто строка"

# но не так:
VARIABLE = "Просто строка"
# Bash решит что VARIABLE - это команда, которую он должен исполнить,
# и выдаст ошибку, потому что не сможет найти ее.

# и не так:
VARIABLE= 'Просто строка'
# Тут Bash решит, что 'Просто строка' - это команда, которую он должен исполнить,
# и выдаст ошибку, потому что не сможет найти такой команды
# (здесь 'VARIABLE=' выглядит как присвоение значения переменной,
# но только в контексте исполнения команды 'Просто строка').

# Использование переменой:
echo $VARIABLE
echo "$VARIABLE"
echo '$VARIABLE'
# Когда вы используете переменную - присвоение, экспорт и т.д - пишите её
# имя без $. А для получения значения переменной, используйте $.
# Заметте что ' (одинарные кавычки) не раскрывают переменные в них.

# Подстановка строк в переменные
echo ${VARIABLE/Просто/A}
# Это выражение заменит первую встреченную подстроку "Просто" на "A"

# Подстановка из переменной
LENGTH=7
echo ${VARIABLE:0:LENGTH}
# Это выражение вернет только первые 7 символов переменной VARIABLE

# Значение по умолчанию
echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"}
# Это сработает при отсутствующем значении (FOO=) и пустой строке (FOO="");
# ноль (FOO=0) вернет 0.
# Заметте, что в любом случае значение самой переменной FOO не изменится.

# Встроенные переменные:
# В bash есть полезные встроенные переменные, например
echo "Последее возвращенное значение: $?"
echo "PID скрипта: $$"
echo "Количество аргументов: $#"
echo "Аргументы скрипта: $@"
echo "Аргументы скрипта рапределенные по отдельным переменным: $1 $2..."

# Чтение аргументов из входа:
echo "Как Вас зовут?"
read NAME # Заметте, что нам не нужно определять новую переменную
echo Привет, $NAME!

# У нас есть обычная структура if:
# наберите 'man test' для подробностях о форматах условия
if [ $NAME -ne $USER ]
then
    echo "Имя не совпадает с именем пользователя"
else
    echo "Имя совпадает с именем пользователя"
fi

# Также есть условное исполнение
echo "Исполнится всегда" || echo "Исполнится, если первая команда провалится"
echo "Исполнится всегда" && echo "Исполнится, если первая команда выполнится удачно"

# Можно использовать && и || в выражениях if, когда нужно несколько пар скобок:
if [ $NAME == "Steve" ] && [ $AGE -eq 15 ]
then
    echo "Исполнится, если $NAME равно Steve И $AGE равно 15."
fi

if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ]
then
    echo "Исполнится, если $NAME равно Daniya ИЛИ Zach."
fi

# Выражения обозначаются таким форматом:
echo $(( 10 + 5 ))

# В отличае от других языков программирования, bash это командная оболочка -
# значит он работает в контексте текущей директории.
# Вы можете просматривать файлы и директории в текущей директории командой ls:
ls

# У этой команды есть опции:
ls -l # Показать каждый файл и директорию на отдельной строке

# Результат предыдущей команды может быть направлен на вход следующей.
# Команда grep фильтрует ввод по шаблону.
# Так мы можем просмотреть только *.txt файлы в текущей директории:
ls -l | grep "\.txt"

# Вы можете перенаправить ввод и вывод команды (stdin, stdout и stderr).
# Следующая команда означает: читать из stdin пока не встретится ^EOF$ и
# перезаписать hello.py следующим строками (до строки "EOF"):
cat > hello.py << EOF
#!/usr/bin/env python
from __future__ import print_function
import sys
print("#stdout", file=sys.stdout)
print("#stderr", file=sys.stderr)
for line in sys.stdin:
    print(line, file=sys.stdout)
EOF

# Запуск hello.py с разными вариантами перенаправления потоков
# стандартных ввода, вывода и ошибок:
python hello.py < "input.in"
python hello.py > "output.out"
python hello.py 2> "error.err"
python hello.py > "output-and-error.log" 2>&1
python hello.py > /dev/null 2>&1
# Поток ошибок перезапишет файл, если этот файл существует,
# поэтому если вы хотите дописывать файл используйте ">>":
python hello.py >> "output.out" 2>> "error.err"

# Переписать output.txt, дописать error.err и сосчитать строки:
info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err
wc -l output.out error.err

# Запустить команду и вывести ее файловый дескриптор (смотрите: man fd)
echo <(echo "#helloworld")

# Перезаписать output.txt строкой "#helloworld":
cat > output.out <(echo "#helloworld")
echo "#helloworld" > output.out
echo "#helloworld" | cat > output.out
echo "#helloworld" | tee output.out >/dev/null

# Подчистить временные файлы с подробным выводом ('-i' - интерактивый режим)
rm -v output.out error.err output-and-error.log

# Команды могут быть подставлены в строку используя $( ):
# следующие команды выводят число файлов и директорий в текущей директории.
echo "Здесь $(ls | wc -l) элементов."

# То же самое можно сделать использую обратные кавычки, но они не могут быть
# вложенными - предпочтительно использовать $( ).
echo "Здесь `ls | wc -l` элементов."

# В Bash есть структура case, которая похожа на switch в Java и C++:
case "$VARIABLE" in 
    # Перечислите шаблоны для условий, которые хотите отловить
    0) echo "Тут ноль.";;
    1) echo "Тут один.";;
    *) echo "Это не пустое значение.";;
esac

# Цикл for перебирает элементы переданные в аргументе:
# Содержимое $VARIABLE будет напечатано три раза.
for VARIABLE in {1..3}
do
    echo "$VARIABLE"
done

# Или перепишем "традиционным" синтаксисом цикла for:
for ((a=1; a <= 3; a++))
do
    echo $a
done

# Цикл for можно использовать для действий с файлами.
# Запустим команду 'cat' для файлов file1 и file2
for VARIABLE in file1 file2
do
    cat "$VARIABLE"
done

# ..или выводом из команд
# Запустим cat для вывода из ls.
for OUTPUT in $(ls)
do
    cat "$OUTPUT"
done

# Цикл while:
while [ true ]
do
    echo "тело цикла здесь..."
    break
done

# Вы можете определять функции
# Определение:
function foo ()
{
    echo "Аргументы работают также как аругменты скрипта: $@"
    echo "и: $1 $2..."
    echo "Это функция"
    return 0
}

# или просто
bar ()
{
    echo "Другой способ определить функцию!"
    return 0
}

# Вызов функции
foo "Мое имя" $NAME

# Есть много полезных команд, которые нужно знать:
# напечатать последние 10 строк файла file.txt
tail -n 10 file.txt
# напечатать первые 10 строк файла file.txt
head -n 10 file.txt
# отсортировать строки file.txt
sort file.txt
# отобрать или наоборот пропустить повторяющиеся строки (с опцией -d отбирает)
uniq -d file.txt
# напечатать только первую колонку перед символом ','
cut -d ',' -f 1 file.txt
# заменить каждое 'okay' на 'great' в файле file.txt (regex поддерживается)
sed -i 's/okay/great/g' file.txt
# вывести в stdout все строки из file.txt, совпадающие с шаблоном regex;
# этот пример выводит строки, которые начинаются на "foo" и оканчиваются "bar"
grep "^foo.*bar$" file.txt
# передайте опцию -c чтобы вывести число строк, в которых совпал шаблон
grep -c "^foo.*bar$" file.txt
# чтобы искать прямо строку, а не шаблон regex, используйте fgrep (или grep -F)
fgrep "^foo.*bar$" file.txt 


# Читайте встроенную документацию оболочки Bash командой 'help':
help
help help
help for
help return
help source
help .

# Читайте Bash man-документацию
apropos bash
man 1 bash
man bash

# Читайте документацию info (? для помощи)
apropos info | grep '^info.*('
man info
info info
info 5 info

# Читайте bash info документацию:
info bash
info bash 'Bash Features'
info bash 6
info --apropos bash
```