НейроАгент

Как перебирать массивы в Bash-скриптинге

Изучите правильный синтаксис для перебора массивов в Bash-скриптинге. Полное руководство с примерами для итерации по 15 строкам, избегания распространенных ошибок и освоения техник итерации массивов.

Вопрос

Как перебирать массив строк в Bash-скриптинге?

Мне нужно написать скрипт, который перебирает 15 строк, хранящихся в массиве. Возможно ли это в Bash? Вот что я пробовал:

bash
for databaseName in listOfNames
then
  # Do something
done

Какой правильный синтаксис для перебора массива строк в Bash, и как правильно реализовать эту структуру цикла?

НейроАгент

В Bash-скриптинге можно перебирать массив строк с помощью синтаксиса цикла for при правильном объявлении массива и шаблоне итерации. Ваш текущий синтаксис пропускает правильное объявление массива, а ключевое слово then используется неверно - в Bash-циклах для начала тела цикла используется do вместо then.

Содержание


Создание массивов в Bash

Прежде чем перебирать массив, его нужно правильно объявить. Bash поддерживает несколько способов создания массивов:

Индексированные массивы

bash
# Метод 1: Использование круглых скобок
listOfNames=("database1" "database2" "database3")

# Метод 2: Присваивание отдельных элементов
listOfNames[0]="database1"
listOfNames[1]="database2"
listOfNames[2]="database3"

# Метод 3: Использование declare -a
declare -a listOfNames
listOfNames=("db1" "db2" "db3")

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

bash
# Ассоциативные массивы (пары ключ-значение) требуют bash 4+
declare -A db_config
db_config["host"]="localhost"
db_config["port"]="5432"

Базовый синтаксис итерации массива

Вот правильный синтаксис для циклического обхода вашего массива:

bash
# Правильное объявление массива
listOfNames=("database1" "database2" "database3")

# Правильный синтаксис цикла
for databaseName in "${listOfNames[@]}"; do
  # Что-то делаем с databaseName
  echo "Обработка базы данных: $databaseName"
done

Важные элементы, на которые стоит обратить внимание:

  • Используйте do вместо then для начала тела цикла
  • Используйте "${array[@]}" для итерации по всем элементам
  • Переменная цикла (databaseName) последовательно получает каждое значение массива

Полный пример с 15 строками

Вот полный рабочий пример с 15 именами баз данных:

bash
#!/bin/bash

# Создаем массив с 15 именами баз данных
listOfNames=(
  "production_db"
  "staging_db"
  "development_db"
  "testing_db"
  "backup_db"
  "analytics_db"
  "reporting_db"
  "cache_db"
  "session_db"
  "user_db"
  "product_db"
  "order_db"
  "inventory_db"
  "log_db"
  "archive_db"
)

# Цикл по массиву
echo "Начало обработки баз данных..."
echo "============================="

for databaseName in "${listOfNames[@]}"; do
  echo "Обработка базы данных: $databaseName"
  
  # Пример операции: Проверка существования базы данных
  # if psql -U postgres -c "\l" | grep -q "$databaseName"; then
  #   echo "  ✓ База данных существует"
  # else
  #   echo "  ✗ База данных не найдена"
  # fi
  
  # Добавьте здесь вашу логику обработки
  # Подключение к базе данных, выполнение запросов и т.д.
  
  echo "---------------------------"
done

echo "Все базы данных успешно обработаны!"

Различные типы массивов

Индексированные массивы (Наиболее распространенные)

bash
# Стандартный индексированный массив
servers=("web1" "web2" "web3" "db1" "db2")

# Цикл по индексированному массиву
for server in "${servers[@]}"; do
  echo "Сервер: $server"
done

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

bash
# Для ассоциативных массивов требуется bash 4+
declare -A user_roles
user_roles["alice"]="admin"
user_roles["bob"]="developer"
user_roles["charlie"]="user"

# Цикл по ассоциативному массиву
for user in "${!user_roles[@]}"; do
  role="${user_roles[$user]}"
  echo "Пользователь: $user, Роль: $role"
done

Срезы массива

bash
# Получить первые 5 элементов
first_five=("${listOfNames[@]:0:5}")

# Получить элементы с индекса 3 до конца
from_third=("${listOfNames[@]:3}")

Продвинутые техники циклического обхода

Цикл While с индексацией массива

bash
listOfNames=("db1" "db2" "db3")
index=0

while [ $index -lt ${#listOfNames[@]} ]; do
  databaseName="${listOfNames[$index]}"
  echo "Обработка индекса $index: $databaseName"
  ((index++))
done

Цикл For в стиле C

bash
for ((i=0; i<${#listOfNames[@]}; i++)); do
  databaseName="${listOfNames[$i]}"
  echo "Индекс $i: $databaseName"
done

Обработка элементов массива с операциями

bash
# Преобразование массива в верхний регистр
upper_array=("${listOfNames[@]^}")

# Добавление префикса к каждому элементу
prefixed_array=("prod_${listOfNames[@]}")

# Фильтрация элементов массива
filtered_array=($(for name in "${listOfNames[@]}"; do
  [[ $name =~ .*prod.* ]] && echo "$name"
done))

Распространенные ошибки и решения

Ошибка 1: Отсутствие кавычек вокруг массива

bash
# НЕПРАВИЛЬНО - это не будет правильно обрабатывать пробелы
for name in $listOfNames; do

# ПРАВИЛЬНО - используйте кавычки для сохранения пробелов
for name in "${listOfNames[@]}"; do

Ошибка 2: Использование then вместо do

bash
# НЕПРАВИЛЬНО
for name in "${array[@]}"; then

# ПРАВИЛЬНО
for name in "${array[@]}"; do

Ошибка 3: Неправильный доступ к элементам массива

bash
# НЕПРАВИЛЬНО - это ссылается на массив как на одну строку
for name in "$listOfNames"; do

# ПРАВИЛЬНО - используйте [@] для итерации по элементам
for name in "${listOfNames[@]}"; do

Ошибка 4: Забыть объявить массив

bash
# НЕПРАВИЛЬНО - listOfNames - это просто строковая переменная
listOfNames="db1 db2 db3"

# ПРАВИЛЬНО - объявить как массив
listOfNames=("db1" "db2" "db3")

Лучшие практики

  • Всегда используйте синтаксис "${array[@]}" для итерации
  • Используйте кавычки при расширении массива для обработки пробелов и специальных символов
  • Используйте описательные имена переменных
  • Добавьте обработку ошибок для пустых массивов
  • Документируйте содержимое массива в комментариях

Источники

  1. Руководство по Bash для начинающих - Массивы
  2. Продвинутое руководство по Bash-скриптингу - Глава 27 Массивы
  3. Stack Overflow - Итерация по массиву в Bash
  4. GeeksforGeeks - Массивы в Bash
  5. DigitalOcean - Как использовать массивы в Bash-скриптах

Заключение

Циклический обход массивов в Bash-скриптинге прост, как только вы понимаете правильный синтаксис. Ключевые выводы:

  • Всегда правильно объявляйте массивы с помощью круглых скобок: listOfNames=("db1" "db2" "db3")
  • Используйте for variable in "${array[@]}"; do для итерации, а не then
  • Используйте кавычки при расширении массива для обработки пробелов и специальных символов
  • Bash поддерживает как индексированные массивы (с нулевой индексацией), так и ассоциативные массивы (Bash 4+)
  • Вы можете обработать 15 строк или любое количество элементов, используя ту же структуру цикла

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