На главную

Справочники

Шпаргалка bash

Подстановки параметров, массивы, условия и ловушки — с разбором выражения и наглядной разницей «$@» и «$*».

Живой разбор

Проверить подстановку параметра

Поддержаны :- := :? :+ # ## % %% / // : ^ ^^ , ,, и ${#имя}

Результат

error.log

Убран длиннейший префикс, подходящий под «*/».

Почему скрипты ломаются на пробелах

«$@» против «$*»

Разделяйте точкой с запятой — так видно, где кончается аргумент с пробелом.

ФормаЧто получит командаСлов
"$@"одиндва словатриКаждый аргумент остаётся отдельным словом целиком. Единственная безопасная форма.3
"$*"один два слова триОдно слово: аргументы склеены первым символом IFS (пробел).1
$@одиндвасловатриКавычек нет — каждое значение дополнительно рвётся по пробелам.4
$*одиндвасловатриБез кавычек ведёт себя так же, как $@: склейка теряется при разбиении слов.4

Показано 77 из 77 строк.

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

Двоеточие в форме означает «пустая строка считается за отсутствие». Без двоеточия пустая строка — полноценное значение.

  • ${name:-по умолчанию}

    Значение, а если пусто или не задано — подставить текст. Саму переменную не меняет.

  • ${name-по умолчанию}

    То же, но пустая строка считается заданным значением.

  • ${name:=по умолчанию}

    Подставить и заодно присвоить переменной.

  • ${name:?нужен name}

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

  • ${name:+--flag}

    Подставить текст только если переменная непуста — удобно для необязательных флагов.

  • ${#name}

    Длина значения в символах.

  • ${name#*/}

    Убрать кратчайший префикс по шаблону.

  • ${name##*/}

    Убрать длиннейший префикс — то же, что basename.

  • ${name%/*}

    Убрать кратчайший суффикс — то же, что dirname.

  • ${name%%.*}

    Убрать длиннейший суффикс — имя файла без всех расширений.

  • ${name/старое/новое}

    Заменить первое вхождение.

  • ${name//старое/новое}

    Заменить все вхождения.

  • ${name/#пре/новое}

    Заменить только в начале; /% — только в конце.

  • ${name:7:3}

    Подстрока: смещение 7, длина 3. Отрицательное смещение — через пробел: ${name: -3}.

  • ${name^^}

    ВЕРХНИЙ регистр целиком; ^ — только первая буква.

  • ${name,,}

    нижний регистр целиком; , — только первая буква.

  • ${!prefix*}

    Имена всех переменных, начинающихся с prefix.

  • ${!name}

    Косвенная ссылка: значение переменной, чьё имя лежит в name.

Аргументы и специальные переменные

"$@" в кавычках — единственная форма, которая переживает пробелы в аргументах. Всё остальное рано или поздно ломается на пути «Мои документы».

  • "$@"

    Все аргументы, каждый — отдельным словом. Это правильный вариант.

  • "$*"

    Все аргументы одной строкой через первый символ IFS (обычно пробел).

  • $@ без кавычек

    Каждый аргумент дополнительно рвётся по пробелам — почти всегда ошибка.

  • $#

    Сколько аргументов передано.

  • $0

    Имя самого скрипта.

  • $1 … $9, ${10}

    Позиционные аргументы; с десятого — обязательно в фигурных скобках.

  • $?

    Код возврата предыдущей команды. 0 — успех.

  • $$

    PID текущего скрипта; $! — PID последнего фонового процесса.

  • shift 2

    Сдвинуть аргументы: $3 становится $1.

  • set -- a b c

    Переписать список позиционных аргументов.

  • local -n ref=$1

    Ссылка на переменную по имени внутри функции (bash 4.3+).

Массивы и ассоциативные массивы

  • arr=(один два "три с пробелом")

    Объявление обычного массива.

  • "${arr[@]}"

    Все элементы, каждый отдельным словом. В кавычках — обязательно.

  • ${#arr[@]}

    Число элементов; ${#arr[0]} — длина первого.

  • ${arr[-1]}

    Последний элемент (bash 4.3+).

  • "${arr[@]:1:2}"

    Срез: два элемента начиная со второго.

  • arr+=(ещё)

    Добавить в конец.

  • for x in "${arr[@]}"; do echo "$x"; done

    Правильный перебор массива.

  • declare -A map

    Ассоциативный массив; без объявления bash сделает обычный и молча испортит ключи.

  • map[ключ]=значение

    Запись; ${map[ключ]} — чтение.

  • "${!map[@]}"

    Все ключи; "${map[@]}" — все значения.

  • mapfile -t lines < file.txt

    Файл в массив строк без завершающих переводов строки.

  • IFS=, read -ra parts <<< "$csv"

    Разбить строку по запятой в массив.

Условия и сравнения

[[ ]] — встроенная конструкция bash: не рвёт слова, понимает && и =~. [ ] — внешняя команда, там каждую переменную надо брать в кавычки.

  • [[ -z "$s" ]]

    Строка пуста; -n — непуста.

  • [[ "$a" == "$b" ]]

    Строки равны; != — не равны.

  • [[ "$s" == п* ]]

    Справа шаблон, а не строка: без кавычек это сравнение с образцом.

  • [[ "$s" =~ ^[0-9]+$ ]]

    Регулярное выражение; группы попадают в ${BASH_REMATCH[1]}.

  • (( a > b ))

    Арифметическое сравнение. Внутри знак $ перед именами не нужен.

  • [[ "$a" -eq "$b" ]]

    Числовое равенство: -eq -ne -lt -le -gt -ge.

  • [[ -f "$f" ]]

    Обычный файл существует; -d — каталог, -e — что угодно, -L — ссылка.

  • [[ -s "$f" ]]

    Файл существует и непустой.

  • [[ -r "$f" && -w "$f" ]]

    Доступен на чтение и запись.

  • [[ "$f1" -nt "$f2" ]]

    Первый файл новее второго; -ot — старее.

  • if command -v jq >/dev/null; then …; fi

    Проверить, что программа установлена.

  • case "$1" in start) … ;; stop) … ;; *) … ;; esac

    Разбор по вариантам вместо лестницы if.

Надёжный скрипт: ловушки и защита

  • set -Eeuo pipefail

    Падать на ошибке, на необъявленной переменной и на ошибке внутри конвейера. Первая строка любого скрипта.

  • IFS=$'\n\t'

    Убрать пробел из разделителей — меньше сюрпризов при разбиении слов.

  • trap cleanup EXIT

    Выполнить функцию при любом выходе, в том числе по ошибке.

  • trap 'echo "строка $LINENO"' ERR

    Показать, где именно упало (нужен set -E).

  • tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT

    Временный каталог, который уберётся сам.

  • command || true

    Разрешить одной команде упасть, не роняя скрипт с set -e.

  • if ! out=$(cmd 2>&1); then echo "$out" >&2; exit 1; fi

    Поймать вывод и код возврата разом.

  • exec 200>/var/lock/my.lock; flock -n 200 || exit 1

    Не дать скрипту запуститься дважды.

  • readonly CONFIG=/etc/app.conf

    Константа: переприсваивание станет ошибкой.

  • printf '%s\n' "$var"

    Безопасная печать: echo калечит строки, начинающиеся с - или содержащие \n.

  • "${BASH_SOURCE[0]}"

    Путь к самому скрипту даже при source; $0 в этом случае врёт.

  • cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1

    Перейти в каталог скрипта, что бы ни было текущим.

Потоки, конвейеры, подстановки

  • cmd > out.txt 2>&1

    И вывод, и ошибки в файл. Порядок важен: 2>&1 > file так не работает.

  • cmd &> out.txt

    То же короче (bash).

  • cmd 2>/dev/null

    Выбросить только ошибки.

  • cmd >> out.txt

    Дописать в конец, а не перезаписать.

  • out=$(cmd)

    Подстановка команды. Обратные кавычки — устаревшая форма, не вкладываются.

  • diff <(cmd1) <(cmd2)

    Подстановка процесса: вывод команды как файл.

  • cat <<'EOF' > file

    Heredoc. Кавычки вокруг EOF отключают подстановку переменных внутри.

  • cat <<-EOF

    Дефис позволяет отбивать тело табуляциями.

  • read -r line <<< "$string"

    Herestring: строка на вход команде.

  • while IFS= read -r line; do echo "$line"; done < file

    Правильное чтение файла по строкам: IFS= сохраняет отступы, -r не ест \.

  • cmd | tee -a log.txt

    И на экран, и в файл.

  • set -o pipefail

    Код возврата конвейера — от первой упавшей команды, а не от последней.