Введение
Этот учебник проведет вас через процесс понимания и использования ассоциативных массивов (key-value arrays) в Bash для ваших скриптов. Ассоциативные массивы - это мощные структуры данных, которые позволяют хранить и извлекать данные, используя описательные ключи вместо числовых индексов.
К концу этого учебника вы сможете создавать, манипулировать и использовать ассоциативные массивы в ваших скриптах Bash, чтобы более эффективно организовывать данные и решать задачи, которые были бы сложны с традиционными числовыми массивами.
Создание вашего первого ассоциативного массива Bash
Ассоциативные массивы (key-value arrays) в Bash позволяют вам связывать значения с определенными ключами, аналогично словарям в Python или объектам в JavaScript. Это делает их идеальными для хранения структурированных данных, где элементы идентифицируются по именам, а не по позициям.
Основной синтаксис
Чтобы работать с ассоциативными массивами в Bash, вы должны сначала объявить их, используя опцию -A:
declare -A myarray
Это создает пустой ассоциативный массив с именем myarray. Флаг -A специально сообщает Bash, что это ассоциативный (key-value) массив.
Добавление элементов в массив
Давайте создадим ассоциативный массив для хранения информации о разных фруктах:
- Откройте новый терминал в WebIDE, если он еще не открыт
- Создайте новый файл скрипта, нажав "File > New File" в WebIDE
- Сохраните файл как
fruit_array.shв каталоге/home/labex/project - Добавьте следующий код в файл:
#!/bin/bash
## Declare a key-value array
declare -A fruits
## Add elements to the array
fruits["apple"]="red"
fruits["banana"]="yellow"
fruits["grape"]="purple"
fruits["orange"]="orange"
## Print a specific element
echo "The color of an apple is ${fruits["apple"]}"
## Print all values
echo "All fruit colors: ${fruits[@]}"
## Print all keys
echo "All fruits: ${!fruits[@]}"
- Сохраните файл (Ctrl+S или File > Save)
- Сделайте скрипт исполняемым с помощью следующей команды в терминале:
chmod +x fruit_array.sh
- Запустите скрипт:
./fruit_array.sh
Вы должны увидеть вывод, похожий на этот:
The color of an apple is red
All fruit colors: red yellow purple orange
All fruits: apple banana grape orange
Понимание вывода
${fruits["apple"]}: Этот синтаксис извлекает значение, связанное с ключом "apple"${fruits[@]}: Это возвращает все значения в массиве${!fruits[@]}: Символ!перед именем массива возвращает все ключи в массиве
Ассоциативные массивы Bash позволяют вам получать доступ к данным напрямую, используя понятные имена, а не запоминать числовые позиции, что делает ваши скрипты более читаемыми и удобными в обслуживании.
Манипулирование ассоциативными массивами Bash
Теперь, когда вы понимаете основы ассоциативных массивов, давайте рассмотрим, как ими манипулировать. На этом этапе вы узнаете, как изменять существующие значения, добавлять новые элементы, удалять элементы и проверять, существует ли ключ.
Создание нового скрипта
- Создайте новый файл с именем
array_operations.shв каталоге/home/labex/project - Добавьте следующий код в файл:
#!/bin/bash
## Declare a key-value array
declare -A user_info
## Add initial elements
user_info["name"]="John Doe"
user_info["email"]="john@example.com"
user_info["age"]="30"
user_info["city"]="New York"
## Display initial array content
echo "--- Initial user information ---"
for key in "${!user_info[@]}"; do
echo "$key: ${user_info[$key]}"
done
## Modify an existing value
user_info["age"]="31"
## Add a new key-value pair
user_info["country"]="USA"
## Check if a key exists
if [[ -v user_info["email"] ]]; then
echo -e "\nEmail exists: ${user_info["email"]}"
else
echo -e "\nEmail does not exist"
fi
## Remove an element
unset 'user_info[city]'
## Display the modified array
echo -e "\n--- Modified user information ---"
for key in "${!user_info[@]}"; do
echo "$key: ${user_info[$key]}"
done
## Count the number of elements
echo -e "\nNumber of elements: ${#user_info[@]}"
- Сохраните файл (Ctrl+S или File > Save)
- Сделайте скрипт исполняемым:
chmod +x array_operations.sh
- Запустите скрипт:
./array_operations.sh
Вы должны увидеть вывод, похожий на этот:
--- Initial user information ---
name: John Doe
email: john@example.com
age: 30
city: New York
Email exists: john@example.com
--- Modified user information ---
name: John Doe
country: USA
email: john@example.com
age: 31
Number of elements: 4
Объяснение ключевых операций
- Изменение значений: Просто присвойте новое значение существующему ключу:
user_info["age"]="31" - Добавление новых элементов: Используйте тот же синтаксис, что и при начальном присвоении:
user_info["country"]="USA" - Проверка существования ключа: Используйте оператор теста
-v:[[ -v user_info["email"] ]] - Удаление элементов: Используйте команду
unset:unset 'user_info[city]' - Подсчет элементов: Используйте
${#array[@]}, чтобы получить количество элементов - Итерация по элементам: Используйте цикл for с
${!array[@]}, чтобы получить все ключи
Обратите внимание, как пара ключ-значение city удалена в измененном выводе, и добавлена новая пара ключ-значение country. Также значение age было обновлено с 30 до 31.
Эти операции важны при работе с динамическими данными в ваших скриптах, позволяя вам обновлять информацию по мере необходимости.
Создание практического менеджера конфигурации
Теперь, когда вы понимаете, как создавать и манипулировать ассоциативными массивами, давайте создадим что-то практичное. На этом этапе вы создадите простой менеджер конфигурации, который загружает настройки из файла конфигурации, хранит их в ассоциативном массиве и позволяет вам получать к ним доступ.
Шаг 1: Создание файла конфигурации
Сначала давайте создадим файл конфигурации с некоторыми примерами настроек:
- Создайте новый файл с именем
app_config.txtв каталоге/home/labex/project - Добавьте следующее содержимое в файл:
database_host=localhost
database_port=3306
database_user=admin
database_password=secret123
app_name=MyAwesomeApp
debug_mode=true
max_connections=100
- Сохраните файл
Шаг 2: Создание скрипта менеджера конфигурации
Теперь давайте создадим скрипт, который будет читать этот файл конфигурации и хранить его содержимое в ассоциативном массиве:
- Создайте новый файл с именем
config_manager.shв каталоге/home/labex/project - Добавьте следующий код в файл:
#!/bin/bash
## Define the path to the configuration file
CONFIG_FILE="/home/labex/project/app_config.txt"
## Declare a key-value array for the configuration
declare -A config
## Function to load configuration from file
load_config() {
local file=$1
## Check if the file exists
if [[ ! -f "$file" ]]; then
echo "Error: Configuration file '$file' not found."
return 1
fi
## Read the file line by line
while IFS='=' read -r key value; do
## Skip empty lines and comments
if [[ -z "$key" || "$key" == \#* ]]; then
continue
fi
## Store the key-value pair in the array
config["$key"]="$value"
done < "$file"
echo "Configuration loaded successfully from '$file'"
return 0
}
## Function to get a configuration value
get_config() {
local key=$1
local default=$2
## Check if the key exists
if [[ -v config["$key"] ]]; then
echo "${config["$key"]}"
else
echo "$default"
fi
}
## Function to display all configuration
display_config() {
echo "--- Configuration Settings ---"
for key in "${!config[@]}"; do
echo "$key = ${config[$key]}"
done
}
## Load the configuration
load_config "$CONFIG_FILE"
## Display all configuration settings
display_config
## Example of getting specific configuration values
echo -e "\n--- Example Usage ---"
db_host=$(get_config "database_host" "127.0.0.1")
db_port=$(get_config "database_port" "5432")
db_user=$(get_config "database_user" "root")
db_pass=$(get_config "database_password" "")
app_name=$(get_config "app_name" "DefaultApp")
debug_mode=$(get_config "debug_mode" "false")
echo "Database connection: $db_user@$db_host:$db_port"
echo "Application name: $app_name"
echo "Debug mode: $debug_mode"
## Example of getting a non-existent value (will use default)
timeout=$(get_config "connection_timeout" "30")
echo "Connection timeout: $timeout (default value used)"
- Сохраните файл (Ctrl+S или File > Save)
- Сделайте скрипт исполняемым:
chmod +x config_manager.sh
- Запустите скрипт:
./config_manager.sh
Вы должны увидеть вывод, похожий на этот:
Configuration loaded successfully from '/home/labex/project/app_config.txt'
--- Configuration Settings ---
database_host = localhost
database_port = 3306
database_user = admin
database_password = secret123
app_name = MyAwesomeApp
debug_mode = true
max_connections = 100
--- Example Usage ---
Database connection: admin@localhost:3306
Application name: MyAwesomeApp
Debug mode: true
Connection timeout: 30 (default value used)
Понимание менеджера конфигурации
Скрипт, который вы создали, выполняет несколько важных действий:
- Он читает пары ключ-значение из файла конфигурации
- Он хранит эти пары в ассоциативном массиве
- Он предоставляет функции для:
- Загрузки конфигурации из файла
- Получения конкретных значений конфигурации с резервными значениями по умолчанию
- Отображения всех настроек конфигурации
Этот шаблон обычно используется в реальных приложениях для управления настройками конфигурации. Основные преимущества:
- Централизованная конфигурация: Все настройки находятся в одном месте
- Значения по умолчанию: Если настройка отсутствует, можно использовать значение по умолчанию
- Легкий доступ: Доступ к настройкам можно получить по имени
- Гибкость: Конфигурацию можно обновить, не изменяя скрипт
Этот пример демонстрирует, как ассоциативные массивы можно использовать для решения практических задач в скриптинге оболочки. Вы можете расширить его, добавив функции для сохранения изменений обратно в файл конфигурации или для проверки настроек.
Создание скрипта с меню на основе ассоциативных массивов
На этом заключительном этапе мы создадим практичный скрипт с меню, который использует ассоциативные массивы для хранения и обработки выбора пользователя. Этот пример демонстрирует, как ассоциативные массивы можно использовать для создания более интерактивных и удобных для пользователя приложений командной строки.
Создание системы меню
- Создайте новый файл с именем
menu_system.shв каталоге/home/labex/project - Добавьте следующий код в файл:
#!/bin/bash
## Declare a key-value array for menu options
declare -A menu_options
menu_options["1"]="Display system information"
menu_options["2"]="Check disk usage"
menu_options["3"]="List running processes"
menu_options["4"]="View network connections"
menu_options["q"]="Quit"
## Declare a key-value array for commands to execute
declare -A menu_commands
menu_commands["1"]="display_system_info"
menu_commands["2"]="check_disk_usage"
menu_commands["3"]="list_processes"
menu_commands["4"]="view_network"
## Function to display system information
display_system_info() {
echo -e "\n--- System Information ---"
echo "Hostname: $(hostname)"
echo "Kernel version: $(uname -r)"
echo "System uptime: $(uptime -p)"
echo "CPU information: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d ':' -f 2 | xargs)"
echo "Total memory: $(free -h | grep Mem | awk '{print $2}')"
}
## Function to check disk usage
check_disk_usage() {
echo -e "\n--- Disk Usage ---"
df -h | grep -v tmp
}
## Function to list running processes
list_processes() {
echo -e "\n--- Top 10 Processes by Memory Usage ---"
ps aux --sort=-%mem | head -11
}
## Function to view network connections
view_network() {
echo -e "\n--- Active Network Connections ---"
netstat -tuln | grep LISTEN
}
## Function to display the menu
display_menu() {
echo -e "\n=== System Utility Menu ==="
for key in 1 2 3 4 q; do
echo "$key. ${menu_options[$key]}"
done
echo -e "\nPlease enter your choice:"
}
## Main loop
while true; do
## Display the menu
display_menu
## Read user choice
read -r choice
## Check if choice is valid
if [[ -v menu_options["$choice"] ]]; then
## Exit if user chose quit
if [[ "$choice" == "q" ]]; then
echo "Exiting. Goodbye!"
exit 0
fi
## Execute the corresponding command
if [[ -v menu_commands["$choice"] ]]; then
## Call the function associated with the choice
${menu_commands["$choice"]}
fi
else
echo "Invalid option. Please try again."
fi
## Pause for user to read output
echo -e "\nPress Enter to continue..."
read -r
done
- Сохраните файл (Ctrl+S или File > Save)
- Сделайте скрипт исполняемым:
chmod +x menu_system.sh
- Запустите скрипт:
./menu_system.sh
- Попробуйте разные пункты меню, вводя соответствующий номер, затем нажмите Enter, когда появится запрос, чтобы вернуться в меню. Введите
q, чтобы выйти из программы, когда закончите.
Понимание системы меню
Этот скрипт демонстрирует несколько продвинутых способов использования ассоциативных массивов:
- Пункты меню: Массив
menu_optionsсопоставляет номера опций с описательным текстом - Сопоставление команд: Массив
menu_commandsсопоставляет номера опций с именами функций - Динамическое выполнение: Скрипт использует значение из одного массива, чтобы определить, какую функцию вызывать
Преимущества использования ассоциативных массивов в этой системе меню включают:
- Удобство обслуживания: Добавление или изменение пунктов меню требует только обновления массивов
- Читаемость: Код четко показывает, какая команда соответствует какому пункту меню
- Гибкость: Вы можете легко переупорядочить пункты меню, не изменяя вызовы функций
Этот шаблон полезен для создания интерактивных инструментов командной строки, которые легко поддерживать и расширять.
Основные выводы
В течение этого руководства вы узнали:
- Как создавать и инициализировать ассоциативные массивы в Bash
- Как получать доступ, изменять и удалять элементы из ассоциативных массивов
- Как перебирать ключи и значения в ассоциативном массиве
- Как использовать ассоциативные массивы для хранения данных конфигурации
- Как создать интерактивную систему меню, используя ассоциативные массивы
Эти методы можно применять к широкому спектру задач скриптинга оболочки, от простого хранения данных до сложных интерактивных приложений.
Резюме
В этом руководстве вы изучили мощь и универсальность ассоциативных массивов (key-value arrays) в Bash. Начиная с основ, вы узнали, как создавать и получать доступ к ассоциативным массивам, а затем перешли к более сложным операциям, таким как изменение, добавление и удаление элементов.
Вы применили эти знания для создания практических примеров, включая менеджер конфигурации, который считывает настройки из файла, и скрипт утилиты с меню, который демонстрирует, как ассоциативные массивы можно использовать для создания интерактивных приложений командной строки.
Ассоциативные массивы предоставляют мощный способ организации и доступа к данным в ваших скриптах Bash. Возможность использовать описательные ключи (keys) вместо числовых индексов делает ваши скрипты более читаемыми и удобными в обслуживании, особенно при работе со сложными структурами данных.
Теперь, когда у вас есть прочное понимание ассоциативных массивов в Bash, вы можете использовать их для улучшения ваших скриптов оболочки и более эффективно решать широкий спектр задач программирования.



