Обзор
В этой статье систематически рассмотрены все специальные конструкции, переменные, правила расширения и управляющие структуры в Bash.
Обозначения переменных
Динамические или зависящие от среды значения обозначаются как <<переменная>>, при этом для каждой конструкции приведён пример использования.
| Имя переменной |
Пример |
Описание |
<<var>> |
name, path, user |
Имя произвольной переменной |
<<default>> |
guest, 8080 |
Значение по умолчанию |
<<pattern>> |
*.txt, */ |
Шаблон файлов или строк |
<<offset>> |
0, 3 |
Начальная позиция подстроки (с нуля) |
<<length>> |
4, 10 |
Длина подстроки |
<<prefix>> |
ENV_, HOST |
Префикс имени переменной |
<<index>> |
0, 1, 2 |
Индекс массива или ключ ассоциативного массива |
<<file>> |
/tmp/test.txt |
Путь к файлу |
Шаг 1: Специальные символы (метасимволы)
| Символ |
Значение |
Пример |
* |
Совпадение с любой строкой |
ls *.txt |
? |
Совпадение с одним символом |
ls ?.sh |
[a-z] |
Диапазон символов |
ls [A-Z]* |
{a,b} |
Расширение фигурных скобок |
mv {foo,bar} |
{1..3} |
Последовательность |
touch file{1..3}.txt |
$ |
Подстановка переменной |
echo $HOME |
! (отрицание) |
Логическое отрицание |
[[ ! -f test.txt ]] |
! (история) |
Расширение истории |
!10 |
~ |
Домашний каталог |
cd ~ |
; |
Последовательное выполнение |
pwd; ls |
&& |
Выполнение при успехе |
make && echo OK |
| ` |
|
` |
& |
Фоновое выполнение |
sleep 5 & |
| ` |
` |
Конвейер |
> |
Перенаправление вывода |
echo hi > out.txt |
>> |
Добавление в файл |
echo hi >> out.txt |
< |
Перенаправление ввода |
wc -l < file.txt |
() |
Подоболочка |
(cd /tmp; ls) |
{} |
Тот же процесс |
{ echo A; echo B; } |
\ |
Экранирование |
echo \$HOME |
' ' |
Без подстановки |
echo '$USER' |
" " |
С подстановкой |
echo "$USER" |
Шаг 2: Специальные переменные
| Переменная |
Содержание |
Пример |
$0 |
Имя скрипта |
echo $0 |
$1〜$9 |
Аргументы |
echo $1 |
$@ |
Массив аргументов |
for a in "$@"; do echo $a; done |
$# |
Количество аргументов |
echo $# |
$? |
Код завершения последней команды |
ls /nope; echo $? |
$$ |
PID текущего процесса |
echo $$ |
$! |
PID последнего фонового процесса |
sleep 10 & echo $! |
$- |
Активные опции оболочки |
echo $- |
$_ |
Последний аргумент предыдущей команды |
echo $_ |
$PPID |
PID родительского процесса |
echo $PPID |
$RANDOM |
Случайное число (0–32767) |
echo $RANDOM |
$SECONDS |
Секунды с момента запуска |
echo $SECONDS |
$FUNCNAME |
Имя функции |
f(){ echo $FUNCNAME; }; f |
$PIPESTATUS[@] |
Коды завершения конвейера |
`ls |
Шаг 3: Расширение параметров
| Синтаксис |
Значение |
Пример |
${<<var>>} |
Подстановка значения |
name=user; echo ${name} |
${<<var>>:-<<default>>} |
Значение по умолчанию |
echo ${user:-guest} |
${<<var>>:=<<default>>} |
Присвоение по умолчанию |
echo ${port:=8080} |
${<<var>>:+alt} |
Альтернатива при определении |
x=1; echo ${x:+OK} |
${<<var>>:?msg} |
Ошибка при неопределённости |
echo ${config:?missing} |
${#<<var>>} |
Длина строки |
name=user; echo ${#name} |
${<<var>>%<<pattern>>} |
Удалить с конца (коротко) |
path=/a/b/c; echo ${path%/*} |
${<<var>>%%<<pattern>>} |
Удалить с конца (длинно) |
echo ${path%%/*} |
${<<var>>#<<pattern>>} |
Удалить с начала (коротко) |
echo ${path#*/} |
${<<var>>##<<pattern>>} |
Удалить с начала (длинно) |
echo ${path##*/} |
${<<var>>/<<pattern>>/<<repl>>} |
Замена первого совпадения |
echo ${msg/foo/bar} |
${<<var>>//<<pattern>>/<<repl>>} |
Замена всех совпадений |
echo ${msg// /_} |
${<<var>>:<<offset>>} |
Подстрока с позиции |
s=abcdef; echo ${s:2} |
${<<var>>:<<offset>>:<<length>>} |
Подстрока длиной |
echo ${s:1:3} |
${!<<prefix>>*} |
Переменные с префиксом |
HOST1=x; HOST2=y; echo ${!HOST*} |
${!<<var>>} |
Косвенная подстановка |
ref=NAME; NAME=user; echo ${!ref} |
${<<var>>,} / ${<<var>>^^} |
Изменение регистра |
n=abc; echo ${n^^} |
${<<var>>@Q} |
Квотирование |
x='abc'; echo ${x@Q} |
Шаг 4: Массивы и ассоциативные массивы
arr=(a b c)
echo ${arr[<<index>>]}
echo ${#arr[@]}
for i in "${arr[@]}"; do echo $i; done
declare -A map
map[<<index>>]=100
map[name]=user
echo ${map[<<index>>]}
echo ${!map[@]}
Шаг 5: Арифметические операции
x=5
y=3
echo $((x + y))
((x *= 2))
echo $x
Шаг 6: Условия и сравнения
if [ "$USER" = "root" ]; then echo root; fi
if [ "$x" -lt 10 ]; then echo "small"; fi
if [ -f /etc/passwd ]; then echo "exists"; fi
s="hello123"
[[ $s =~ [0-9]+ ]] && echo "contains number"
Шаг 7: Подстановка команд и подоболочка
echo "Today: $(date +%Y-%m-%d)"
(cd /tmp; ls)
Шаг 8: Перенаправление и файловые дескрипторы
echo "Hello" > <<file>>
echo "Append" >> <<file>>
wc -l < <<file>>
ls /notfound 2> err.log
echo "OK" >&2
exec 3> custom.log
echo "via fd3" >&3
exec 3>&-
Пояснение: Файловые дескрипторы (FD)
| FD |
Название |
Описание |
Пример |
0 |
stdin |
Ввод с клавиатуры или файла |
< file.txt |
1 |
stdout |
Стандартный вывод |
echo test > out.txt |
2 |
stderr |
Ошибки |
ls /nope 2> err.log |
3+ |
Пользовательские |
Дополнительные потоки |
exec 3> log.txt |
FD3 — дополнительный поток, создаваемый пользователем:
exec 3> process.log
echo "Начало выполнения" >&3
exec 3>&-
Шаг 9: Ловушки и обработка ошибок
set -e
set -u
set -x
set -o pipefail
trap 'echo Завершено' EXIT
trap 'echo Ошибка' ERR
Шаг 10: Управление заданиями
sleep 10 &
jobs
fg %1
bg %1
disown %1
kill %1
Пояснение: номера заданий и %1
sleep 60 &
jobs
Вывод:
[1]+ Running sleep 60 &
[1] — номер задания
%1 — ссылка на задание №1
| Символ |
Значение |
%1 |
Задание №1 |
%+ |
Текущее задание |
%- |
Предыдущее задание |
Шаг 11: Зарезервированные команды
:
true
false
source ~/.bashrc
eval "echo executed"
{ echo A; echo B; }
Итог
Это руководство охватывает все специальные конструкции, переменные, расширения и управляющие элементы Bash. Понимание их позволяет точно анализировать и проектировать скрипты с высокой безопасностью и повторным использованием.