Массивы в Bash: синтаксис и практические приёмы

Массив — это упорядоченный набор значений, доступный по индексу. В Bash массивы индексируются с нуля и по умолчанию одномерны. Ниже — пошаговое объяснение и практические рекомендации.
Основной синтаксис массива
Создать массив в Bash можно так:
city=(London Paris Milan "New York")Это создаёт массив с четырьмя элементами: индексы 0..3. Значения, содержащие пробелы, нужно брать в кавычки, чтобы Bash не разбил их на отдельные элементы.
Доступ к элементу выполняется через индекс в квадратных скобках. Но в Bash при подстановке переменной нужны и знак доллара, и фигурные скобки:
${variable_name[index]}Пример полного скрипта:
#!/bin/bash
city=(London Paris Milan "New York")
echo ${city[3]}
# New YorkАльтернативная запись — постренное присваивание:
#!/bin/bash
city[0]=London
city[1]=Paris
city[2]=Milan
city[3]="New York"
echo ${city[3]}
# New YorkВажно: между именем переменной, индексом и знаком равенства не должно быть пробелов. “city[0] = London” вызовет ошибку.
Частые операции с массивами
- Получить все элементы: ${arr[@]} или ${arr[*]}. Используйте “${arr[@]}” при переборе, чтобы сохранить разделение элементов.
- Длина массива: ${#arr[@]} возвращает количество элементов.
- Добавить элемент: arr+=(value).
- Срез массива: ${arr[@]:s:n} — с позиции s взять n элементов; если n опущено, взять до конца.
Примеры:
echo ${#city[@]}
# 4
city+=(Rome)
echo ${city[@]}
# London Paris Milan New York Rome
echo ${city[@]:2:2}
# Milan New York
echo ${city[@]:3}
# New York RomeМассивы и аргументы командной строки
Можно использовать аргументы скрипта как индекс:
#!/bin/bash
sqrt[1]=1
sqrt[4]=2
sqrt[9]=3
sqrt[16]=4
sqrt[25]=5
echo ${sqrt[$1]}Запуск: ./sqrt.sh 9 выведет 3.
Итерация по массиву
Используйте цикл for с “${arr[@]}” чтобы обойти элементы по отдельности:
for file in "${arr[@]}"; do
wc -l "$file"
doneЗдесь “${arr[@]}” гарантирует, что каждый элемент будет подставлен как отдельный параметр, даже если в названии есть пробелы.
Ассоциативные массивы и отрицательная индексация
Начиная с Bash 4 доступны ассоциативные массивы — словари с ключами-строками. Коротко:
declare -A colors
colors[apple]=red
colors[banana]=yellow
echo ${colors[apple]}
# redОтрицательная индексация для обычных массивов также появилась в более поздних версиях Bash: индекс -1 обозначает последний элемент. Но проверяйте версию Bash у себя в окружении.
Когда массивы в Bash не подходят
- Нужна многомерность. Bash поддерживает только одномерные массивы; эмуляция матриц быстро становится неудобной.
- Сложные структуры данных. Для JSON-объектов, деревьев или больших коллекций лучше использовать Python, Perl или jq.
- Высокая производительность и масштаб. Bash — оболочка, не оптимизирована для тяжёлых вычислений.
Если требуется обработка больших наборов данных, лучше вызвать специализированную программу или перейти на язык общего назначения.
Советы и эвристики
- Всегда кавычьте подстановки: “${arr[@]}” и “$var” — это защитит от проблем с пробелами.
- Для сохранения элементов с пустыми строками используйте правильную IFS-обработку.
- Проверяйте версию Bash при использовании ассоциативных массивов:
bash --version. - Для простых списков файлов используйте
mapfileилиreadarray, чтобы избежать проблем с пробелами:
mapfile -t files < <(ls)
# files теперь массивКороткая шпаргалка
- Создать: arr=(a b c)
- Первый элемент: ${arr[0]}
- Все элементы: “${arr[@]}”
- Длина: ${#arr[@]}
- Добавить: arr+=(value)
- Срез: ${arr[@]:start:length}
- Ассоциативный: declare -A a
Сравнение подходов
- arr=( $(ls) ) — удобно, но риск: невнимание к пробелам приведёт к разбивке имён файлов. Лучше
mapfile -t. - Ассоциативный массив — удобен для пар ключ-значение и более выразителен, чем индексы.
- Для сложной логики лучше вызвать Python/Perl или обработать данные через jq.
Совместимость и версии
- Bash 3: обычные одномерные массивы поддерживаются.
- Bash 4+: добавлены ассоциативные массивы и дополнительные возможности.
Проверьте bash --version на вашей системе перед использованием ассоциативных массивов.
Роль-based чек-лист для разработчиков и инженеров
- Devops/SRE: избегайте дорогостоящих циклов в Bash; используйте массивы для небольших списков и передачи между командами.
- Разработчик скриптов: всегда кавычьте “${arr[@]}” и проверяйте IFS.
- Автоматизатор: для данных с пробелами используйте
mapfileили сериализацию (JSON + jq).
Мини-методология для работы с массивами в скриптах
- Определите объём данных и требуемую структуру (линейный список или ключ-значение).
- Если элементы могут содержать пробелы, используйте
readarray/mapfileили правильно экранируйте. - Для ключ-значение используйте
declare -A(Bash 4+). - Тестируйте скрипт на граничных случаях: пустые элементы, имена с пробелами, специальные символы.
Краткий словарь
- Индекс: позиция элемента в массиве, с нуля.
- ${arr[@]}: все элементы массива как отдельные слова.
- ${arr[*]}: все элементы массива как одно слово при отсутствии кавычек.
- declare -A: объявление ассоциативного массива.
Примеры отказов и как их избежать
Ошибка: разбивка имён файлов с пробелами. Решение:
mapfile -t files < <(ls -1)или использовать find + -print0 с read -d ‘’.Ошибка: попытка использовать многомерный массив. Решение: сериализуйте данные в строку, используйте разделители, или перейдите на другой язык.
Заключение
Массивы в Bash просты, но требуют дисциплины. Для большинства задач на автоматизации и администрировании они подходят отлично. Если задача выходит за рамки одномерных списков или требует высокой производительности, рассмотрите специализированные инструменты.
Важно: проверяйте версию Bash и тестируйте скрипты на реальных данных.
Сводка:
- Массивы в Bash одномерны и индексируются с нуля.
- Используйте “${arr[@]}” при переборе и кавычки для защиты от пробелов.
- Ассоциативные массивы доступны в Bash 4+.