Перейти к основному содержимому

Синтаксис и специальные символы в Bash

Разработчику Архитектору

Play ITЗагрузка интерактивного демо…


Названия знаков по-английски и по-русски: Знаки препинания и символы в IT.

Синтаксис и специальные символы в Bash

Оболочка Bash (Bourne Again Shell) представляет собой сложный интерпретатор команд, который обрабатывает ввод пользователя или скрипта, преобразует его в действия операционной системы и возвращает результат.

В отличие от текстовых редакторов, где знаки препинания служат для структурирования текста, в Bash каждый специальный символ выполняет конкретную техническую функцию — перенаправление потока данных, подстановку значений, управление выполнением команд или создание группировки операций. Ошибка в использовании одного символа может привести к выполнению нежелательных действий, потере данных или аварийному завершению процесса.

Синтаксис Bash включает в себя набор зарезервированных слов, операторов, метасимволов и конструкций. Эти элементы образуют язык, на котором пишутся как простые однострочные команды, так и сложные программные модули. Знание того, как Bash интерпретирует эти символы, позволяет создавать надежные, эффективные и безопасные скрипты.

Как читать эту статью

Сначала — напоминалка по скобкам

раздел "Порядок разбора командной строки", блоки про кавычки и переменные, после этого — перенаправление и pipe. Такой порядок убирает большую часть "магии" Bash.


Порядок разбора командной строки

Перед запуском программы Bash поэтапно преобразует введённую строку. Порядок (упрощённо, по man bash):

  1. Разбиение на токены — слова и операторы (|, >, ;, &&).
  2. Расширения (в таком порядке):
    • фигурные скобки {a,b}, {1..5};
    • тильда ~ → домашний каталог;
    • параметры $var, ${var:-default};
    • подстановка команд $(...);
    • арифметика $(( ... ));
    • подстановка процесса <(...) (только Bash).
  3. Разбиение слов (word splitting) — по символам из IFS (пробел, таб, перевод строки), если слово не в кавычках.
  4. Раскрытие имён (glob, pathname expansion)*, ?, [...] в путях.
  5. Снятие кавычек — в аргументах остаётся итоговый текст.
  6. Перенаправление>, <, &gt;&gt;, 2>, &> связываются с командой.
  7. Выполнение — встроенная команда или exec внешней программы.

Практический вывод — подставляйте переменные как "$path", списки файлов — "$@", а шаблоны вроде *.log оставляйте без кавычек, если нужен glob. Неожиданный разбор — частая причина "пропавших" аргументов и поломки путей с пробелами. Коды возврата и set -e — в Обработка ошибок. Готовые однострочники с кавычками и &gt;&gt;галерея Lab.

files=*.txt # glob после splitting
echo "$files" # одна строка или несколько слов — зависит от числа совпадений
echo "$@" # все аргументы скрипта по отдельности

Основные метасимволы и их назначение

Метасимволы — это специальные знаки, которые имеют особое значение для оболочки и используются для изменения поведения стандартных команд. Они не передаются программам напрямую, а обрабатываются самим Bash перед запуском утилит.


Символ точки .

Символ точка используется для указания относительного пути к файлу или директории. При выполнении команды ./script.sh оболочка ищет файл script.sh в текущей рабочей директории. Без точки система ищет исполняемый файл в директориях, указанных в переменной окружения PATH.

./my_script.sh

В этом случае ./ означает "текущая директория". Если написать просто my_script.sh, Bash будет искать этот файл в системных путях, что может привести к ошибке, если скрипт находится в текущем каталоге, но не имеет прав на выполнение или не зарегистрирован в системе.

Точка также используется как разделитель в именах файлов, например, file.txt, где точка отделяет имя файла от расширения. Однако в контексте путей к файлам точка имеет приоритет над расширением.


Двоеточие :

Двоеточие является встроенной командой, которая ничего не делает, но всегда возвращает код успеха (0). Этот символ часто используют как плейсхолдер для создания пустых блоков кода или для очистки переменных.

: # Пустая команда, возвращает 0

В скриптах двоеточие применяют для инициализации переменных без присваивания им значения или для создания точек входа в циклы, когда тело цикла временно отсутствует.

: ${VARIABLE:=default_value}

В этой конструкции, если переменная VARIABLE не определена, ей присваивается значение по умолчанию default_value. Двоеточие здесь служит для проверки существования переменной без её вывода на экран.


Тире -

Тире используется в двух основных случаях. Во-первых, оно указывает на то, что данные должны быть прочитаны из стандартного ввода (stdin), а не из файла. Во-вторых, тире часто применяется как аргумент для удаления временных файлов или в некоторых утилитах как обозначение отсутствия имени файла.

cat - < input.txt

Здесь cat читает данные из входного потока, который перенаправлен из файла input.txt.

Также тире используется в опциях команд для указания на отсутствие аргумента или для сброса настроек по умолчанию в некоторых программах.


Обратный слэш \

Обратный слэш является символом экранирования. Он используется для того, чтобы Bash воспринял следующий за ним символ как обычный текст, а не как специальный мета-символ. Это необходимо, когда нужно использовать символы, имеющие специальное значение в синтаксисе, в качестве обычных знаков.

echo "Hello \$World"

В этом примере знак доллара экранируется, поэтому Bash выводит его как часть строки, а не пытается выполнить подстановку переменной.

Обратный слэш также используется для продолжения строки на следующую строку в скрипте.

long_command arg1 \
arg2 \
arg3

В такой конструкции обратный слэш сообщает Bash, что команда продолжается на следующей строке. Без него оболочка сочтет конец строки концом команды и выдаст ошибку.


Пробел и табуляция

Пробел и табуляция разделяют слова в команде. Первый пробел отделяет команду от её аргументов, последующие пробелы разделяют сами аргументы.

ls -l /home/user

Здесь ls — команда, -l — первый аргумент, /home/user — второй аргумент. Если убрать пробелы между словами, Bash попытается найти команду с именем, объединяющим все части, что приведет к ошибке.

Табуляция работает аналогично пробелу, но часто используется для форматирования кода в скриптах для улучшения читаемости.

Практический вывод для скриптов: если аргумент может содержать пробелы, его всегда передают в двойных кавычках. Это особенно важно для путей, имен файлов и пользовательского ввода.

file_path="/home/user/My Documents/report.txt"
cat "$file_path"

Без кавычек Bash разобьет строку на несколько аргументов и команда завершится ошибкой.


Перенаправление ввода и вывода

Перенаправление — один из ключевых механизмов Bash, позволяющий управлять потоками данных между командами, файлами и устройствами. Стандартные потоки включают stdin (ввод), stdout (вывод) и stderr (ошибки).


Оператор вывода >

Оператор > перенаправляет стандартный вывод команды в файл. Если файл существует, он перезаписывается. Если файла нет, создается новый.

echo "Привет" > message.txt

Команда создает файл message.txt и записывает в него текст "Привет". Если файл уже содержал данные, они будут полностью удалены.


Оператор добавления &gt;&gt;

Оператор &gt;&gt; перенаправляет вывод команды в файл, добавляя новые данные в конец существующего файла, не удаляя предыдущее содержимое.

echo "Еще одна строка" >> message.txt

Эта команда добавляет новую строку к содержимому файла message.txt.


Перенаправление ошибок 2>

Стандартный поток ошибок (stderr) перенаправляется с помощью оператора 2>. Это позволяет разделить успешный вывод и сообщения об ошибках в разные файлы.

command_that_fails 2> errors.log

Все ошибки, возникающие при выполнении command_that_fails, записываются в файл errors.log, тогда как успешный вывод остается на экране.


Объединение потоков &>

Оператор &> перенаправляет как стандартный вывод, так и поток ошибок в один файл.

command &> all_output.log

Это удобно для логирования всей информации о работе команды в одном месте.


Перенаправление ввода <

Оператор < передает содержимое файла в качестве стандартного ввода для команды.

sort < unsorted_list.txt

Команда sort читает данные из файла unsorted_list.txt и сортирует их, выводя результат на экран.


Перенаправление ввода и вывода <>

Оператор <> открывает файл для чтения и записи одновременно. Это полезно для модификации файлов на месте без создания временных копий.

exec 3< file.txt

В этом случае дескриптор файла 3 открывается для чтения.


Heredoc &lt;&lt;

Heredoc передаёт многострочный текст на stdin команды без отдельного файла. Маркер конца строки — отдельное слово на своей строке (часто EOF).

cat << EOF
Строка 1
Строка 2
EOF

# Без подстановки $ и команд внутри блока — кавычки вокруг маркера
cat << 'EOF'
Сегодня $USER не раскрывается
EOF

В скриптах heredoc удобен для конфигов, SQL и тел писем. С 'EOF' или \EOF защищают содержимое от расширения оболочкой.


Подстановка процесса <() и >()

Bash может подставить имя FIFO или дескриптора, связанного с выводом или вводом команды — как временный "файл-поток".

# Сравнить вывод двух команд без промежуточных файлов
diff <(sort file1.txt) <(sort file2.txt)

# Записать в несколько получателей
tee >(gzip > archive.gz) < data.txt > /dev/null

<(cmd) — чтение результата cmd; >(cmd) — запись в stdin cmd. Это расширение Bash (не POSIX sh); для переносимых скриптов используют временные файлы или mktemp.


Подстановка переменных и команд

Bash поддерживает несколько способов подстановки значений переменных и результатов выполнения команд. Эти механизмы позволяют динамически изменять поведение скриптов.


Знак доллара $

Знак доллара используется для обращения к значению переменной. Без него Bash воспринимает имя как обычную строку.

name="Timur"
echo $name

Выведет: Timur.

Для обращения к аргументам команд используются специальные переменные $1, $2 и т.д., где $1 — первый аргумент, $2 — второй и так далее.

#!/bin/bash
echo "Первый аргумент: $1"
echo "Второй аргумент: $2"

Запуск: ./script.sh hello world

Вывод:

Первый аргумент: hello
Второй аргумент: world

Фигурные скобки ${}

Фигурные скобки окружают имя переменной для четкого разделения имени от остального текста. Это особенно важно, когда после имени переменной следует символ, который может быть частью имени.

var="value"
echo ${var}_suffix

Без скобок echo $var_suffix Bash попытается найти переменную с именем var_suffix, что приведет к ошибке, если такая переменная не определена.

echo $var_suffix

Фигурные скобки также используются для установки значений по умолчанию и обработки отсутствующих переменных.

echo ${HOME:-/tmp}

Если переменная HOME не определена, будет использовано значение /tmp.


Командная подстановка $(...)

Конструкция $(...) выполняет команду и подставляет её вывод вместо самой конструкции. Это современный и предпочтительный способ подстановки команд, заменяющий устаревшие обратные кавычки.

files=$(ls *.txt)
echo "Найдено файлов: $files"

Здесь команда ls *.txt выполняется, её результат (список файлов) подставляется в переменную files.

Командная подстановка также поддерживает вложенность:

count=$(($(date +%s) / 86400))

Обратные кавычки `...`

Обратные кавычки выполняют ту же функцию, что и $(...), но считаются устаревшим синтаксисом. Их использование допустимо в старых скриптах, но рекомендуется заменять на современные аналоги.

files=`ls *.txt`

Логические операторы и условия

Логические операторы позволяют комбинировать команды и строить сложные условия выполнения скриптов.


Амперсанд &&

Оператор && выполняет вторую команду только в том случае, если первая команда завершилась успешно (код возврата 0).

mkdir new_dir && cd new_dir

Команда cd new_dir выполнится только если mkdir new_dir создала директорию без ошибок.


Вертикальная черта ||

Оператор || выполняет вторую команду только в том случае, если первая команда завершилась с ошибкой (код возврата отличен от 0).

cp source.txt dest.txt || echo "Ошибка копирования"

Если команда копирования не удалась, выводится сообщение об ошибке.


Точка с запятой ;

Точка с запятой разделяет команды, позволяя выполнить их последовательно, независимо от результата предыдущей.

cd /home; ls -l; pwd

Все три команды выполнятся подряд, даже если одна из них выдаст ошибку.


Условный оператор if ... then ... fi

Конструкция if позволяет выполнять блоки кода в зависимости от условий.

if [ -f file.txt ]; then
echo "Файл существует"
else
echo "Файл не найден"
fi

Проверка [ -f file.txt ] оценивает существование файла. Если условие истинно, выполняется блок then, иначе — блок else.


Группировка и управление выполнением

Группировка команд позволяет объединять несколько операций в единый блок для управления потоком выполнения.


Скобки ()

Скобки создают подshell, где выполняются команды внутри них. Переменные, определенные внутри скобок, исчезают после завершения блока.

(variable="test")
echo $variable

Переменная variable не будет доступна вне скобок.


Фигурные скобки { }

Фигурные скобки группируют команды в текущей оболочке. Важно: перед открытой фигурной скобкой должен быть пробел или перевод строки, а после закрывающей — точка с запятой или перевод строки.

{
echo "Команда 1"
echo "Команда 2"
} > output.txt

Все команды внутри фигурных скобок выполняются, а их общий вывод перенаправляется в файл.


Парентезы [[ ]]

Конструкция [[ ]] — это расширение тестовой команды, которое поддерживает регулярные выражения и более сложную логику.

if [[ $name == "Timur"* ]]; then
echo "Имя начинается на Timur"
fi

Здесь используется шаблонное сравнение с подстановкой звездочки.


Глобальные паттерны и подстановки

Globs (шаблоны) позволяют работать с множеством файлов одновременно, используя специальные символы.


Астериск *

Астериск заменяет любое количество любых символов в имени файла.

ls *.txt

Показывает все файлы с расширением .txt.


Вопросительный знак ?

Вопросительный знак заменяет ровно один символ.

ls file?.txt

Показывает файлы вроде file1.txt, fileA.txt, но не file10.txt.


Квадратные скобки []

Квадратные скобки определяют диапазон или набор символов.

ls file[1-3].txt

Показывает файлы file1.txt, file2.txt, file3.txt.

ls file[!a-c].txt

Показывает файлы, где буква после file не входит в диапазон a-c.


Кавычки и экранирование

Кавычки защищают содержимое от интерпретации Bash.


Одинарные кавычки ' '

Одинарные кавычки защищают всё содержимое от интерпретации. Ни $, ни `, ни другие спецсимволы не работают внутри.

echo 'Hello $USER'

Выведет: Hello $USER.


Двойные кавычки " "

Двойные кавычки разрешают подстановку переменных и команд, но защищают от глобальных паттернов.

echo "Hello $USER"

Выведет имя пользователя.

Практическое правило:

  • для литерала без подстановок используйте '...';
  • для строк с переменными и $(...) используйте "...";
  • избегайте "голых" переменных в командах, если это не осознанное поведение.

Экранирование \

Обратный слэк экранирует следующие символы.

echo "Price is \$100"

Выведет: Price is $100.


Разбиение слов (word splitting)

После подстановки "$var" и `...` / $(...) оболочка режет результат по символам из **IFS** (пробел, таб, перевод строки). Поэтому пути и аргументы с пробелами всегда берут в кавычки: "$file", "$@". Имена файлов из find или циклов — "$&#123;array[@]&#125;", не $*.


Специальные переменные и константы

Bash предоставляет ряд специальных переменных, которые автоматически обновляются во время выполнения скрипта.


$?

Переменная $? содержит код возврата последней выполненной команды.

ls nonexistent_file
echo $?

Выведет 2 (или другой код ошибки).


$#

Переменная $# содержит количество аргументов, переданных скрипту.

echo "Количество аргументов: $#"

$@ и $*

$@ и $* содержат все аргументы скрипта. Разница в том, что $@ сохраняет каждый аргумент как отдельную единицу, а $* объединяет их в одну строку.

for arg in "$@"; do
echo "Аргумент: $arg"
done

$0

Переменная $0 содержит имя скрипта или оболочки.

echo "Скрипт: $0"

$PWD и $OLDPWD

$PWD содержит текущую рабочую директорию, $OLDPWD — предыдущую.

cd /tmp
echo "Текущая: $PWD"
echo "Предыдущая: $OLDPWD"

Обработка ошибок и безопасность

Безопасное написание скриптов требует внимания к обработке ошибок и использованию правильных синтаксических конструкций.


Установка флагов безопасности

Флаги set -e, set -u, set -o pipefail помогают избежать скрытых ошибок.

set -e # Выход при первой ошибке
set -u # Ошибка при обращении к неопределенной переменной
set -o pipefail # Ошибка, если хотя бы одна команда в конвейере падает

Использование trap

Команда trap позволяет перехватывать сигналы и выполнять очистку перед завершением скрипта.

trap "rm -f temp_file" EXIT

При завершении скрипта файл temp_file будет удален.


Проверка существования переменных

if [ -z "${VAR+x}" ]; then
VAR="default"
fi

Проверка существования переменной без её использования.


Примеры сложных конструкций

Конвейеры и фильтрация

# Предпочтительнее — без лишнего процесса grep в списке
pkill -f '[p]ython' # или: pgrep -f python | xargs -r kill

Завершение процессов по имени; kill -9 — крайняя мера, сначала пробуйте обычный TERM.


Циклы с условиями

for file in *.log; do
if [ -s "$file" ]; then
echo "Обработка $file"
gzip "$file"
fi
done

Цикл по всем лог-файлам, проверка на непустоту и архивация.


Работа с массивами

array=("apple" "banana" "cherry")
for item in "${array[@]}"; do
echo "$item"
done

Вывод всех элементов массива.


Содержание