Das Verwenden von assoziativen Arrays in Bash bei der Schreibung von Shell-Skripten

ShellShellBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Introduction

This tutorial will guide you through the process of understanding and utilizing Bash key-value arrays (also known as associative arrays) in your shell scripting. Key-value arrays are powerful data structures that allow you to store and retrieve data using descriptive keys instead of numeric indices.

By the end of this tutorial, you will be able to create, manipulate, and use key-value arrays in your Bash scripts to organize data more effectively and solve problems that would be difficult with traditional numeric arrays.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL shell(("Shell")) -.-> shell/VariableHandlingGroup(["Variable Handling"]) shell(("Shell")) -.-> shell/ControlFlowGroup(["Control Flow"]) shell(("Shell")) -.-> shell/FunctionsandScopeGroup(["Functions and Scope"]) shell/VariableHandlingGroup -.-> shell/variables_decl("Variable Declaration") shell/VariableHandlingGroup -.-> shell/variables_usage("Variable Usage") shell/VariableHandlingGroup -.-> shell/arrays("Arrays") shell/ControlFlowGroup -.-> shell/while_loops("While Loops") shell/FunctionsandScopeGroup -.-> shell/func_def("Function Definition") subgraph Lab Skills shell/variables_decl -.-> lab-413759{{"Das Verwenden von assoziativen Arrays in Bash bei der Schreibung von Shell-Skripten"}} shell/variables_usage -.-> lab-413759{{"Das Verwenden von assoziativen Arrays in Bash bei der Schreibung von Shell-Skripten"}} shell/arrays -.-> lab-413759{{"Das Verwenden von assoziativen Arrays in Bash bei der Schreibung von Shell-Skripten"}} shell/while_loops -.-> lab-413759{{"Das Verwenden von assoziativen Arrays in Bash bei der Schreibung von Shell-Skripten"}} shell/func_def -.-> lab-413759{{"Das Verwenden von assoziativen Arrays in Bash bei der Schreibung von Shell-Skripten"}} end

Creating Your First Bash Key-Value Array

Bash key-value arrays (also called associative arrays) allow you to associate values with specific keys, similar to dictionaries in Python or objects in JavaScript. This makes them ideal for storing structured data where items are identified by names rather than positions.

Basic Syntax

To work with key-value arrays in Bash, you must first declare them using the -A option:

declare -A myarray

This creates an empty key-value array named myarray. The -A flag specifically tells Bash that this is an associative (key-value) array.

Adding Elements to the Array

Let's create a key-value array to store information about different fruits:

  1. Open a new terminal in the WebIDE if one is not already open
  2. Create a new script file by clicking "File > New File" in the WebIDE
  3. Save the file as fruit_array.sh in the /home/labex/project directory
  4. Add the following code to the file:
#!/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[@]}"
  1. Save the file (Ctrl+S or File > Save)
  2. Make the script executable with the following command in the terminal:
chmod +x fruit_array.sh
  1. Run the script:
./fruit_array.sh

You should see output similar to this:

The color of an apple is red
All fruit colors: red yellow purple orange
All fruits: apple banana grape orange

Understanding the Output

  • ${fruits["apple"]}: This syntax retrieves the value associated with the key "apple"
  • ${fruits[@]}: This returns all values in the array
  • ${!fruits[@]}: The ! symbol before the array name returns all keys in the array

Bash key-value arrays allow you to access data directly using meaningful names rather than having to remember numeric positions, making your scripts more readable and maintainable.

Manipulating Bash Key-Value Arrays

Now that you understand the basics of key-value arrays, let's explore how to manipulate them. In this step, you'll learn how to modify existing values, add new elements, remove elements, and check if a key exists.

Creating a New Script

  1. Create a new file called array_operations.sh in the /home/labex/project directory
  2. Add the following code to the file:
#!/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[@]}"
  1. Save the file (Ctrl+S or File > Save)
  2. Make the script executable:
chmod +x array_operations.sh
  1. Run the script:
./array_operations.sh

You should see output similar to this:

--- 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

Key Operations Explained

  • Modifying values: Simply assign a new value to an existing key: user_info["age"]="31"
  • Adding new elements: Use the same syntax as initial assignment: user_info["country"]="USA"
  • Checking if a key exists: Use the -v test operator: [[ -v user_info["email"] ]]
  • Removing elements: Use the unset command: unset 'user_info[city]'
  • Counting elements: Use ${#array[@]} to get the number of elements
  • Iterating through elements: Use a for loop with ${!array[@]} to get all keys

Notice how the city key-value pair is removed in the modified output, and a new country key-value pair has been added. Also, the age value has been updated from 30 to 31.

These operations are essential when working with dynamic data in your scripts, allowing you to update information as needed.

Creating a Practical Configuration Manager

Now that you understand how to create and manipulate key-value arrays, let's build something practical. In this step, you'll create a simple configuration manager that loads settings from a config file, stores them in a key-value array, and allows you to access them.

Step 1: Create a Configuration File

First, let's create a configuration file with some sample settings:

  1. Create a new file called app_config.txt in the /home/labex/project directory
  2. Add the following content to the file:
database_host=localhost
database_port=3306
database_user=admin
database_password=secret123
app_name=MyAwesomeApp
debug_mode=true
max_connections=100
  1. Save the file

Step 2: Create the Configuration Manager Script

Now, let's create a script that will read this configuration file and store its contents in a key-value array:

  1. Create a new file called config_manager.sh in the /home/labex/project directory
  2. Add the following code to the file:
#!/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)"
  1. Save the file (Ctrl+S or File > Save)
  2. Make the script executable:
chmod +x config_manager.sh
  1. Run the script:
./config_manager.sh

You should see output similar to this:

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)

Understanding the Configuration Manager

The script you've created does several important things:

  1. It reads key-value pairs from a configuration file
  2. It stores these pairs in a key-value array
  3. It provides functions to:
    • Load configuration from a file
    • Get specific configuration values with default fallbacks
    • Display all configuration settings

This pattern is commonly used in real-world applications to manage configuration settings. The key benefits are:

  • Centralized configuration: All settings are in one place
  • Default values: If a setting is missing, a default value can be used
  • Easy access: Settings can be accessed by name
  • Flexibility: Configuration can be updated without changing the script

This example demonstrates how key-value arrays can be used to solve practical problems in shell scripting. You could extend this by adding functions to save changes back to the configuration file or to validate settings.

In this final step, we'll create a practical menu-driven script that uses key-value arrays to store and process user selections. This example demonstrates how key-value arrays can be used to create more interactive and user-friendly command-line applications.

  1. Create a new file called menu_system.sh in the /home/labex/project directory
  2. Add the following code to the file:
#!/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
  1. Save the file (Ctrl+S or File > Save)
  2. Make the script executable:
chmod +x menu_system.sh
  1. Run the script:
./menu_system.sh
  1. Try the different menu options by entering the corresponding number, then press Enter when prompted to return to the menu. Enter q to quit the program when you're done.

This script demonstrates several advanced uses of key-value arrays:

  1. Menu Options: The menu_options array maps option numbers to descriptive text
  2. Command Mapping: The menu_commands array maps option numbers to function names
  3. Dynamic Execution: The script uses the value from one array to determine which function to call

The benefits of using key-value arrays in this menu system include:

  • Maintainability: Adding or modifying menu options only requires updating the arrays
  • Readability: The code clearly shows which command corresponds to which menu option
  • Flexibility: You can easily reorder menu items without changing function calls

This pattern is useful for creating interactive command-line tools that are easy to maintain and extend.

Key Takeaways

Throughout this tutorial, you've learned:

  1. How to create and initialize key-value arrays in Bash
  2. How to access, modify, and remove elements from key-value arrays
  3. How to iterate through keys and values in a key-value array
  4. How to use key-value arrays to store configuration data
  5. How to create an interactive menu system using key-value arrays

These techniques can be applied to a wide range of shell scripting tasks, from simple data storage to complex interactive applications.

Summary

In this tutorial, you have explored the power and versatility of Bash key-value arrays. Starting with the basics, you learned how to create and access key-value arrays, then progressed to more advanced operations such as modifying, adding, and removing elements.

You applied this knowledge to create practical examples, including a configuration manager that reads settings from a file and a menu-driven utility script that demonstrates how key-value arrays can be used to create interactive command-line applications.

Key-value arrays provide a powerful way to organize and access data in your Bash scripts. The ability to use descriptive keys instead of numeric indices makes your scripts more readable and maintainable, especially when dealing with complex data structures.

Now that you have a solid understanding of key-value arrays in Bash, you can use them to enhance your shell scripts and solve a wide range of programming challenges more efficiently.